Merge remote-tracking branch 'springsource/3.2.x' into cleanup-3.2.x
* springsource/3.2.x: (143 commits) Remove eclipse project specific Javadoc settings Increment version to 3.2.2.BUILD-SNAPSHOT Release version 3.2.1.RELEASE Tweak gradle generated eclipse meta-data Completed changelog entries for 3.2.1 Avoid UnsupportedOperationEx. with active SecurityManager Made EncodedResource based variant public; consistently detect XML properties across all variants Added note on thread safety to TypeConverter and SimpleTypeConverter javadoc Change merge.into project dependencies to provided Final preparations for 3.2.1 Polishing Removed pre-JDK-1.5 checks ResourcePropertyResource accepts EncodedResource for properties files with a specific encoding Updated resolvePath javadoc to reflect Environment-based placeholder resolution DisposableBeanAdapter detects "shutdown" as a destroy method as well (for EHCache CacheManager setup) Added further MySQL error code for DataIntegrityViolationException ThreadPoolExecutorFactoryBean exposes "createExecutor" method for custom ThreadPoolExecutor subclasses MBeanInfoAssembler impls expose actual method parameter names if possible Suppress serialization warning Allow nulls with multiple embedded value resolvers ...
This commit is contained in:
commit
36b5ba1871
|
|
@ -13,8 +13,6 @@ jmx.log
|
||||||
derby.log
|
derby.log
|
||||||
spring-test/test-output/
|
spring-test/test-output/
|
||||||
.gradle
|
.gradle
|
||||||
.classpath
|
|
||||||
.project
|
|
||||||
argfile*
|
argfile*
|
||||||
pom.xml
|
pom.xml
|
||||||
|
|
||||||
|
|
@ -22,6 +20,11 @@ pom.xml
|
||||||
buildSrc/build
|
buildSrc/build
|
||||||
/spring-*/build
|
/spring-*/build
|
||||||
|
|
||||||
|
# Eclipse artifacts, including WTP generated manifests
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
|
spring-*/src/main/java/META-INF/MANIFEST.MF
|
||||||
|
|
||||||
# IDEA artifacts and output dirs
|
# IDEA artifacts and output dirs
|
||||||
*.iml
|
*.iml
|
||||||
*.ipr
|
*.ipr
|
||||||
|
|
|
||||||
49
build.gradle
49
build.gradle
|
|
@ -3,7 +3,7 @@ buildscript {
|
||||||
maven { url "http://repo.springsource.org/plugins-release" }
|
maven { url "http://repo.springsource.org/plugins-release" }
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.1")
|
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.3")
|
||||||
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.4")
|
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.4")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -21,8 +21,6 @@ configure(allprojects) { project ->
|
||||||
|
|
||||||
apply plugin: "propdeps"
|
apply plugin: "propdeps"
|
||||||
apply plugin: "java"
|
apply plugin: "java"
|
||||||
apply plugin: "propdeps-eclipse"
|
|
||||||
apply plugin: "propdeps-idea"
|
|
||||||
apply plugin: "test-source-set-dependencies"
|
apply plugin: "test-source-set-dependencies"
|
||||||
apply from: "${gradleScriptDir}/ide.gradle"
|
apply from: "${gradleScriptDir}/ide.gradle"
|
||||||
|
|
||||||
|
|
@ -60,7 +58,7 @@ configure(allprojects) { project ->
|
||||||
|
|
||||||
test {
|
test {
|
||||||
systemProperty("java.awt.headless", "true")
|
systemProperty("java.awt.headless", "true")
|
||||||
systemProperty("testGroups", properties.get("testGroups"))
|
systemProperty("testGroups", project.properties.get("testGroups"))
|
||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
|
|
@ -235,7 +233,9 @@ project("spring-core") {
|
||||||
optional("net.sf.jopt-simple:jopt-simple:3.0")
|
optional("net.sf.jopt-simple:jopt-simple:3.0")
|
||||||
optional("log4j:log4j:1.2.17")
|
optional("log4j:log4j:1.2.17")
|
||||||
testCompile("xmlunit:xmlunit:1.3")
|
testCompile("xmlunit:xmlunit:1.3")
|
||||||
testCompile("org.codehaus.woodstox:wstx-asl:3.2.7")
|
testCompile("org.codehaus.woodstox:wstx-asl:3.2.7") {
|
||||||
|
exclude group: "stax", module: "stax-api"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
jar {
|
jar {
|
||||||
|
|
@ -526,8 +526,8 @@ project("spring-orm-hibernate4") {
|
||||||
description = "Spring Object/Relational Mapping - Hibernate 4 support"
|
description = "Spring Object/Relational Mapping - Hibernate 4 support"
|
||||||
merge.into = project(":spring-orm")
|
merge.into = project(":spring-orm")
|
||||||
dependencies {
|
dependencies {
|
||||||
compile(project(":spring-tx"))
|
provided(project(":spring-tx"))
|
||||||
compile(project(":spring-jdbc"))
|
provided(project(":spring-jdbc"))
|
||||||
optional("org.hibernate:hibernate-core:4.1.0.Final")
|
optional("org.hibernate:hibernate-core:4.1.0.Final")
|
||||||
optional("org.hibernate:hibernate-entitymanager:4.1.0.Final")
|
optional("org.hibernate:hibernate-entitymanager:4.1.0.Final")
|
||||||
optional(project(":spring-web"))
|
optional(project(":spring-web"))
|
||||||
|
|
@ -597,8 +597,8 @@ project("spring-webmvc-tiles3") {
|
||||||
description = "Spring Framework Tiles3 Integration"
|
description = "Spring Framework Tiles3 Integration"
|
||||||
merge.into = project(":spring-webmvc")
|
merge.into = project(":spring-webmvc")
|
||||||
dependencies {
|
dependencies {
|
||||||
compile(project(":spring-context"))
|
provided(project(":spring-context"))
|
||||||
compile(project(":spring-web"))
|
provided(project(":spring-web"))
|
||||||
provided("javax.el:el-api:1.0")
|
provided("javax.el:el-api:1.0")
|
||||||
provided("javax.servlet:jstl:1.2")
|
provided("javax.servlet:jstl:1.2")
|
||||||
provided("javax.servlet.jsp:jsp-api:2.1")
|
provided("javax.servlet.jsp:jsp-api:2.1")
|
||||||
|
|
@ -613,6 +613,9 @@ project("spring-webmvc-tiles3") {
|
||||||
optional("org.apache.tiles:tiles-jsp:3.0.1") {
|
optional("org.apache.tiles:tiles-jsp:3.0.1") {
|
||||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||||
}
|
}
|
||||||
|
optional("org.apache.tiles:tiles-extras:3.0.1") {
|
||||||
|
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||||
|
}
|
||||||
optional("org.apache.tiles:tiles-el:3.0.1") {
|
optional("org.apache.tiles:tiles-el:3.0.1") {
|
||||||
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
exclude group: "org.slf4j", module: "jcl-over-slf4j"
|
||||||
}
|
}
|
||||||
|
|
@ -640,10 +643,22 @@ project("spring-webmvc-portlet") {
|
||||||
|
|
||||||
project("spring-test") {
|
project("spring-test") {
|
||||||
description = "Spring TestContext Framework"
|
description = "Spring TestContext Framework"
|
||||||
test {
|
|
||||||
useJUnit()
|
task testNG(type: Test) {
|
||||||
useTestNG()
|
useTestNG()
|
||||||
|
// "TestCase" classes are run by other test classes, not the build.
|
||||||
|
exclude "**/*TestCase.class"
|
||||||
|
// Generate TestNG reports alongside JUnit reports.
|
||||||
|
testReport true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
test {
|
||||||
|
dependsOn testNG
|
||||||
|
useJUnit()
|
||||||
|
// "TestCase" classes are run by other test classes, not the build.
|
||||||
|
exclude(["**/*TestCase.class", "**/*TestSuite.class"])
|
||||||
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile(project(":spring-core"))
|
compile(project(":spring-core"))
|
||||||
optional(project(":spring-beans"))
|
optional(project(":spring-beans"))
|
||||||
|
|
@ -674,8 +689,8 @@ project("spring-test-mvc") {
|
||||||
description = "Spring Test MVC Framework"
|
description = "Spring Test MVC Framework"
|
||||||
merge.into = project(":spring-test")
|
merge.into = project(":spring-test")
|
||||||
dependencies {
|
dependencies {
|
||||||
optional(project(":spring-context"))
|
provided(project(":spring-context"))
|
||||||
compile(project(":spring-webmvc"))
|
provided(project(":spring-webmvc"))
|
||||||
provided("javax.servlet:javax.servlet-api:3.0.1")
|
provided("javax.servlet:javax.servlet-api:3.0.1")
|
||||||
optional("org.hamcrest:hamcrest-core:1.3")
|
optional("org.hamcrest:hamcrest-core:1.3")
|
||||||
optional("com.jayway.jsonpath:json-path:0.8.1")
|
optional("com.jayway.jsonpath:json-path:0.8.1")
|
||||||
|
|
@ -752,6 +767,7 @@ configure(rootProject) {
|
||||||
|
|
||||||
apply plugin: "docbook-reference"
|
apply plugin: "docbook-reference"
|
||||||
apply plugin: "groovy"
|
apply plugin: "groovy"
|
||||||
|
apply plugin: "detect-split-packages"
|
||||||
apply from: "${gradleScriptDir}/jdiff.gradle"
|
apply from: "${gradleScriptDir}/jdiff.gradle"
|
||||||
|
|
||||||
reference {
|
reference {
|
||||||
|
|
@ -759,7 +775,11 @@ configure(rootProject) {
|
||||||
pdfFilename = "spring-framework-reference.pdf"
|
pdfFilename = "spring-framework-reference.pdf"
|
||||||
}
|
}
|
||||||
|
|
||||||
// don"t publish the default jar for the root project
|
detectSplitPackages {
|
||||||
|
projectsToScan -= project(":spring-instrument-tomcat")
|
||||||
|
}
|
||||||
|
|
||||||
|
// don't publish the default jar for the root project
|
||||||
configurations.archives.artifacts.clear()
|
configurations.archives.artifacts.clear()
|
||||||
|
|
||||||
dependencies { // for integration tests
|
dependencies { // for integration tests
|
||||||
|
|
@ -959,6 +979,7 @@ configure(rootProject) {
|
||||||
"set GRADLE_OPTS=$gradleBatOpts %GRADLE_OPTS%\nset DEFAULT_JVM_OPTS=")
|
"set GRADLE_OPTS=$gradleBatOpts %GRADLE_OPTS%\nset DEFAULT_JVM_OPTS=")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,158 @@
|
||||||
|
/*
|
||||||
|
* 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.build.gradle
|
||||||
|
|
||||||
|
import org.gradle.api.DefaultTask
|
||||||
|
import org.gradle.api.GradleException
|
||||||
|
import org.gradle.api.Plugin
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.tasks.Input
|
||||||
|
import org.gradle.api.tasks.TaskAction
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gradle plugin that detects identically named, non-empty packages split across multiple
|
||||||
|
* subprojects, e.g. "org.springframework.context.annotation" existing in both spring-core
|
||||||
|
* and spring-aspects. Adds a 'detectSplitPackages' task to the current project's task
|
||||||
|
* collection. If the project already contains a 'check' task (i.e. is a typical Gradle
|
||||||
|
* project with the "java" plugin applied), the 'check' task will be updated to depend on
|
||||||
|
* the execution of 'detectSplitPackages'.
|
||||||
|
*
|
||||||
|
* By default, all subprojects will be scanned. Use the 'projectsToScan' task property to
|
||||||
|
* modify this value. Example usage:
|
||||||
|
*
|
||||||
|
* apply plugin: 'detect-split-packages // typically applied to root project
|
||||||
|
*
|
||||||
|
* detectSplitPackages {
|
||||||
|
* packagesToScan -= project(":spring-xyz") // scan every project but spring-xyz
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @author Rob Winch
|
||||||
|
* @author Glyn Normington
|
||||||
|
* @author Chris Beams
|
||||||
|
*/
|
||||||
|
public class DetectSplitPackagesPlugin implements Plugin<Project> {
|
||||||
|
public void apply(Project project) {
|
||||||
|
def tasks = project.tasks
|
||||||
|
Task detectSplitPackages = tasks.add("detectSplitPackages", DetectSplitPackagesTask.class)
|
||||||
|
if (tasks.asMap.containsKey("check")) {
|
||||||
|
tasks.getByName("check").dependsOn detectSplitPackages
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DetectSplitPackagesTask extends DefaultTask {
|
||||||
|
|
||||||
|
private static final String JAVA_FILE_SUFFIX = ".java"
|
||||||
|
private static final String PACKAGE_SEPARATOR = "."
|
||||||
|
private static final String HIDDEN_DIRECTORY_PREFIX = "."
|
||||||
|
|
||||||
|
@Input
|
||||||
|
Set<Project> projectsToScan = project.subprojects
|
||||||
|
|
||||||
|
public DetectSplitPackagesTask() {
|
||||||
|
this.group = "Verification"
|
||||||
|
this.description = "Detects packages split across two or more subprojects."
|
||||||
|
}
|
||||||
|
|
||||||
|
@TaskAction
|
||||||
|
public void detectSplitPackages() {
|
||||||
|
def splitPackages = doDetectSplitPackages()
|
||||||
|
if (!splitPackages.isEmpty()) {
|
||||||
|
def message = "The following split package(s) have been detected:\n"
|
||||||
|
splitPackages.each { pkg, mod ->
|
||||||
|
message += " - ${pkg} (split across ${mod[0].name} and ${mod[1].name})\n"
|
||||||
|
}
|
||||||
|
throw new GradleException(message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, List<Project>> doDetectSplitPackages() {
|
||||||
|
def splitPackages = [:]
|
||||||
|
def mergedProjects = findMergedProjects()
|
||||||
|
def packagesByProject = mapPackagesByProject()
|
||||||
|
|
||||||
|
def projects = packagesByProject.keySet().toArray()
|
||||||
|
def nProjects = projects.length
|
||||||
|
|
||||||
|
for (int i = 0; i < nProjects - 1; i++) {
|
||||||
|
for (int j = i + 1; j < nProjects - 1; j++) {
|
||||||
|
def prj_i = projects[i]
|
||||||
|
def prj_j = projects[j]
|
||||||
|
|
||||||
|
def pkgs_i = new HashSet(packagesByProject.get(prj_i))
|
||||||
|
def pkgs_j = packagesByProject.get(prj_j)
|
||||||
|
pkgs_i.retainAll(pkgs_j)
|
||||||
|
|
||||||
|
if (!pkgs_i.isEmpty()
|
||||||
|
&& mergedProjects.get(prj_i) != prj_j
|
||||||
|
&& mergedProjects.get(prj_j) != prj_i) {
|
||||||
|
pkgs_i.each { pkg ->
|
||||||
|
def readablePkg = pkg.substring(1).replaceAll(File.separator, PACKAGE_SEPARATOR)
|
||||||
|
splitPackages[readablePkg] = [prj_i, prj_j]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return splitPackages;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Project, Set<String>> mapPackagesByProject() {
|
||||||
|
def packagesByProject = [:]
|
||||||
|
this.projectsToScan.each { Project p ->
|
||||||
|
def packages = new HashSet<String>()
|
||||||
|
p.sourceSets.main.java.srcDirs.each { File dir ->
|
||||||
|
findPackages(packages, dir, "")
|
||||||
|
}
|
||||||
|
if (!packages.isEmpty()) {
|
||||||
|
packagesByProject.put(p, packages)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return packagesByProject;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<Project, Project> findMergedProjects() {
|
||||||
|
def mergedProjects = [:]
|
||||||
|
this.projectsToScan.findAll { p ->
|
||||||
|
p.plugins.findPlugin(MergePlugin)
|
||||||
|
}.findAll { p ->
|
||||||
|
p.merge.into
|
||||||
|
}.each { p ->
|
||||||
|
mergedProjects.put(p, p.merge.into)
|
||||||
|
}
|
||||||
|
return mergedProjects
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void findPackages(Set<String> packages, File dir, String packagePath) {
|
||||||
|
def scanDir = new File(dir, packagePath)
|
||||||
|
def File[] javaFiles = scanDir.listFiles({ file ->
|
||||||
|
!file.isDirectory() && file.name.endsWith(JAVA_FILE_SUFFIX)
|
||||||
|
} as FileFilter)
|
||||||
|
|
||||||
|
if (javaFiles != null && javaFiles.length != 0) {
|
||||||
|
packages.add(packagePath)
|
||||||
|
}
|
||||||
|
|
||||||
|
scanDir.listFiles({ File file ->
|
||||||
|
file.isDirectory() && !file.name.startsWith(HIDDEN_DIRECTORY_PREFIX)
|
||||||
|
} as FileFilter).each { File subDir ->
|
||||||
|
findPackages(packages, dir, packagePath + File.separator + subDir.name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
implementation-class=org.springframework.build.gradle.DetectSplitPackagesPlugin
|
||||||
|
|
@ -1 +1 @@
|
||||||
version=3.2.1.BUILD-SNAPSHOT
|
version=3.2.2.BUILD-SNAPSHOT
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,12 @@
|
||||||
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
|
import org.gradle.plugins.ide.eclipse.model.ProjectDependency
|
||||||
|
import org.gradle.plugins.ide.eclipse.model.SourceFolder
|
||||||
|
|
||||||
|
|
||||||
|
apply plugin: "propdeps-eclipse"
|
||||||
|
apply plugin: "propdeps-idea"
|
||||||
|
|
||||||
|
// Replace classpath entries with project dependencies (GRADLE-1116)
|
||||||
eclipse.classpath.file.whenMerged { classpath ->
|
eclipse.classpath.file.whenMerged { classpath ->
|
||||||
// GRADLE-1116
|
|
||||||
def regexp = /.*?\/([^\/]+)\/build\/[^\/]+\/(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
|
def regexp = /.*?\/([^\/]+)\/build\/[^\/]+\/(?:main|test)/ // only match those that end in main or test (avoids removing necessary entries like build/classes/jaxb)
|
||||||
def projectOutputDependencies = classpath.entries.findAll { entry -> entry.path =~ regexp }
|
def projectOutputDependencies = classpath.entries.findAll { entry -> entry.path =~ regexp }
|
||||||
projectOutputDependencies.each { entry ->
|
projectOutputDependencies.each { entry ->
|
||||||
|
|
@ -19,3 +24,76 @@ eclipse.classpath.file.whenMerged { classpath ->
|
||||||
}
|
}
|
||||||
classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) }
|
classpath.entries.removeAll { entry -> (entry.path =~ /(?!.*?repack.*\.jar).*?\/([^\/]+)\/build\/libs\/[^\/]+\.jar/) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Use separate main/test outputs (prevents WTP from packaging test classes)
|
||||||
|
eclipse.classpath.defaultOutputDir = file(project.name+"/bin/eclipse")
|
||||||
|
eclipse.classpath.file.beforeMerged { classpath ->
|
||||||
|
classpath.entries.findAll{ it instanceof SourceFolder }.each {
|
||||||
|
if(it.output.startsWith("bin/")) {
|
||||||
|
it.output = null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
eclipse.classpath.file.whenMerged { classpath ->
|
||||||
|
classpath.entries.findAll{ it instanceof SourceFolder }.each {
|
||||||
|
it.output = "bin/" + it.path.split("/")[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allow projects to be used as WPT modules
|
||||||
|
eclipse.project.natures "org.eclipse.wst.common.project.facet.core.nature"
|
||||||
|
|
||||||
|
|
||||||
|
// Include project specific settings
|
||||||
|
task eclipseSettings(type: Copy) {
|
||||||
|
from rootProject.files(
|
||||||
|
"src/eclipse/org.eclipse.jdt.ui.prefs",
|
||||||
|
"src/eclipse/org.eclipse.wst.common.project.facet.core.xml")
|
||||||
|
into project.file('.settings/')
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
task eclipseWstComponent(type: Copy) {
|
||||||
|
from rootProject.files(
|
||||||
|
"src/eclipse/org.eclipse.wst.common.component")
|
||||||
|
into project.file('.settings/')
|
||||||
|
expand(deployname: project.name)
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
task eclipseJdtPrepare(type: Copy) {
|
||||||
|
from rootProject.file("src/eclipse/org.eclipse.jdt.core.prefs")
|
||||||
|
into project.file(".settings/")
|
||||||
|
outputs.upToDateWhen { false }
|
||||||
|
}
|
||||||
|
|
||||||
|
task cleanEclipseJdtUi(type: Delete) {
|
||||||
|
delete project.file(".settings/org.eclipse.jdt.ui.prefs")
|
||||||
|
delete project.file("org.eclipse.jdt.core.prefs")
|
||||||
|
delete project.file(".settings/org.eclipse.wst.common.component")
|
||||||
|
delete project.file(".settings/org.eclipse.wst.common.project.facet.core.xml")
|
||||||
|
}
|
||||||
|
|
||||||
|
tasks["eclipseJdt"].dependsOn(eclipseJdtPrepare)
|
||||||
|
tasks["cleanEclipse"].dependsOn(cleanEclipseJdtUi)
|
||||||
|
tasks["eclipse"].dependsOn(eclipseSettings, eclipseWstComponent)
|
||||||
|
|
||||||
|
|
||||||
|
// Filter 'build' folder
|
||||||
|
|
||||||
|
eclipse.project.file.withXml {
|
||||||
|
def node = it.asNode()
|
||||||
|
|
||||||
|
def filteredResources = node.get("filteredResources")
|
||||||
|
if(filteredResources) {
|
||||||
|
node.remove(filteredResources)
|
||||||
|
}
|
||||||
|
def filterNode = node.appendNode("filteredResources").appendNode("filter")
|
||||||
|
filterNode.appendNode("id", "1359048889071")
|
||||||
|
filterNode.appendNode("name", "")
|
||||||
|
filterNode.appendNode("type", "30")
|
||||||
|
def matcherNode = filterNode.appendNode("matcher")
|
||||||
|
matcherNode.appendNode("id", "org.eclipse.ui.ide.multiFilter")
|
||||||
|
matcherNode.appendNode("arguments", "1.0-projectRelativePath-matches-false-false-build")
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -47,7 +47,7 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig
|
||||||
*/
|
*/
|
||||||
private int order = Ordered.LOWEST_PRECEDENCE;
|
private int order = Ordered.LOWEST_PRECEDENCE;
|
||||||
|
|
||||||
private final Map<String, Boolean> eligibleBeans = new ConcurrentHashMap<String, Boolean>(64);
|
private final Map<Class, Boolean> eligibleBeans = new ConcurrentHashMap<Class, Boolean>(64);
|
||||||
|
|
||||||
|
|
||||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||||
|
|
@ -94,19 +94,21 @@ public abstract class AbstractAdvisingBeanPostProcessor extends ProxyConfig
|
||||||
/**
|
/**
|
||||||
* Check whether the given bean is eligible for advising with this
|
* Check whether the given bean is eligible for advising with this
|
||||||
* post-processor's {@link Advisor}.
|
* post-processor's {@link Advisor}.
|
||||||
* <p>Implements caching of {@code canApply} results per bean name.
|
* <p>Implements caching of {@code canApply} results per bean target class.
|
||||||
|
* Can be overridden e.g. to specifically exclude certain beans by name.
|
||||||
* @param bean the bean instance
|
* @param bean the bean instance
|
||||||
* @param beanName the name of the bean
|
* @param beanName the name of the bean
|
||||||
|
* @see AopUtils#getTargetClass(Object)
|
||||||
* @see AopUtils#canApply(Advisor, Class)
|
* @see AopUtils#canApply(Advisor, Class)
|
||||||
*/
|
*/
|
||||||
protected boolean isEligible(Object bean, String beanName) {
|
protected boolean isEligible(Object bean, String beanName) {
|
||||||
Boolean eligible = this.eligibleBeans.get(beanName);
|
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
||||||
|
Boolean eligible = this.eligibleBeans.get(targetClass);
|
||||||
if (eligible != null) {
|
if (eligible != null) {
|
||||||
return eligible;
|
return eligible;
|
||||||
}
|
}
|
||||||
Class<?> targetClass = AopUtils.getTargetClass(bean);
|
|
||||||
eligible = AopUtils.canApply(this.advisor, targetClass);
|
eligible = AopUtils.canApply(this.advisor, targetClass);
|
||||||
this.eligibleBeans.put(beanName, eligible);
|
this.eligibleBeans.put(targetClass, eligible);
|
||||||
return eligible;
|
return eligible;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,9 @@ task compileJava(overwrite: true) {
|
||||||
inputs.files(project.sourceSets.main.allSource + project.sourceSets.main.compileClasspath)
|
inputs.files(project.sourceSets.main.allSource + project.sourceSets.main.compileClasspath)
|
||||||
outputs.dir outputDir
|
outputs.dir outputDir
|
||||||
|
|
||||||
|
ext.sourceCompatibility = project(":spring-core").compileJava.sourceCompatibility
|
||||||
|
ext.targetCompatibility = project(":spring-core").compileJava.targetCompatibility
|
||||||
|
|
||||||
doLast{
|
doLast{
|
||||||
ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties",
|
ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties",
|
||||||
classpath: configurations.ajc.asPath)
|
classpath: configurations.ajc.asPath)
|
||||||
|
|
@ -30,7 +33,7 @@ task compileJava(overwrite: true) {
|
||||||
destDir: outputDir.absolutePath,
|
destDir: outputDir.absolutePath,
|
||||||
aspectPath: configurations.aspects.asPath,
|
aspectPath: configurations.aspects.asPath,
|
||||||
inpath: configurations.ajInpath.asPath,
|
inpath: configurations.ajInpath.asPath,
|
||||||
sourceRootCopyFilter: "**/*.java",
|
sourceRootCopyFilter: "**/*.java,**/*.aj",
|
||||||
classpath: (sourceSets.main.runtimeClasspath + configurations.rt).asPath) {
|
classpath: (sourceSets.main.runtimeClasspath + configurations.rt).asPath) {
|
||||||
sourceroots {
|
sourceroots {
|
||||||
sourceSets.main.java.srcDirs.each {
|
sourceSets.main.java.srcDirs.each {
|
||||||
|
|
@ -51,6 +54,9 @@ task compileTestJava(overwrite: true) {
|
||||||
inputs.files(project.sourceSets.test.allSource + project.sourceSets.test.compileClasspath)
|
inputs.files(project.sourceSets.test.allSource + project.sourceSets.test.compileClasspath)
|
||||||
outputs.dir outputDir
|
outputs.dir outputDir
|
||||||
|
|
||||||
|
ext.sourceCompatibility = project(":spring-core").compileTestJava.sourceCompatibility
|
||||||
|
ext.targetCompatibility = project(":spring-core").compileTestJava.targetCompatibility
|
||||||
|
|
||||||
doLast{
|
doLast{
|
||||||
ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties",
|
ant.taskdef(resource: "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties",
|
||||||
classpath: configurations.ajc.asPath)
|
classpath: configurations.ajc.asPath)
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.beans.factory.aspectj;
|
package org.springframework.beans.factory.aspectj;
|
||||||
|
|
||||||
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||||
|
|
@ -23,12 +23,12 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||||
* Abstract superaspect for AspectJ aspects that can perform Dependency
|
* Abstract superaspect for AspectJ aspects that can perform Dependency
|
||||||
* Injection on objects, however they may be created. Define the beanCreation()
|
* Injection on objects, however they may be created. Define the beanCreation()
|
||||||
* pointcut in subaspects.
|
* pointcut in subaspects.
|
||||||
*
|
*
|
||||||
* <p>Subaspects may also need a metadata resolution strategy, in the
|
* <p>Subaspects may also need a metadata resolution strategy, in the
|
||||||
* {@code BeanWiringInfoResolver} interface. The default implementation
|
* <code>BeanWiringInfoResolver</code> interface. The default implementation
|
||||||
* looks for a bean with the same name as the FQN. This is the default name
|
* looks for a bean with the same name as the FQN. This is the default name
|
||||||
* of a bean in a Spring container if the id value is not supplied explicitly.
|
* of a bean in a Spring container if the id value is not supplied explicitly.
|
||||||
*
|
*
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
* @author Adrian Colyer
|
* @author Adrian Colyer
|
||||||
|
|
@ -62,7 +62,7 @@ public abstract aspect AbstractBeanConfigurerAspect extends BeanConfigurerSuppor
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The initialization of a new object.
|
* The initialization of a new object.
|
||||||
*
|
*
|
||||||
* <p>WARNING: Although this pointcut is non-abstract for backwards
|
* <p>WARNING: Although this pointcut is non-abstract for backwards
|
||||||
* compatibility reasons, it is meant to be overridden to select
|
* compatibility reasons, it is meant to be overridden to select
|
||||||
* initialization of any configurable bean.
|
* initialization of any configurable bean.
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -21,7 +21,7 @@ import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||||
/**
|
/**
|
||||||
* Abstract base aspect that can perform Dependency
|
* Abstract base aspect that can perform Dependency
|
||||||
* Injection on objects, however they may be created.
|
* Injection on objects, however they may be created.
|
||||||
*
|
*
|
||||||
* @author Ramnivas Laddad
|
* @author Ramnivas Laddad
|
||||||
* @since 2.5.2
|
* @since 2.5.2
|
||||||
*/
|
*/
|
||||||
|
|
@ -29,26 +29,26 @@ public abstract aspect AbstractDependencyInjectionAspect {
|
||||||
/**
|
/**
|
||||||
* Select construction join points for objects to inject dependencies
|
* Select construction join points for objects to inject dependencies
|
||||||
*/
|
*/
|
||||||
public abstract pointcut beanConstruction(Object bean);
|
public abstract pointcut beanConstruction(Object bean);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select deserialization join points for objects to inject dependencies
|
* Select deserialization join points for objects to inject dependencies
|
||||||
*/
|
*/
|
||||||
public abstract pointcut beanDeserialization(Object bean);
|
public abstract pointcut beanDeserialization(Object bean);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select join points in a configurable bean
|
* Select join points in a configurable bean
|
||||||
*/
|
*/
|
||||||
public abstract pointcut inConfigurableBean();
|
public abstract pointcut inConfigurableBean();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select join points in beans to be configured prior to construction?
|
* Select join points in beans to be configured prior to construction?
|
||||||
* By default, use post-construction injection matching the default in the Configurable annotation.
|
* By default, use post-construction injection matching the default in the Configurable annotation.
|
||||||
*/
|
*/
|
||||||
public pointcut preConstructionConfiguration() : if(false);
|
public pointcut preConstructionConfiguration() : if(false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select the most-specific initialization join point
|
* Select the most-specific initialization join point
|
||||||
* (most concrete class) for the initialization of an instance.
|
* (most concrete class) for the initialization of an instance.
|
||||||
*/
|
*/
|
||||||
public pointcut mostSpecificSubTypeConstruction() :
|
public pointcut mostSpecificSubTypeConstruction() :
|
||||||
|
|
@ -58,25 +58,25 @@ public abstract aspect AbstractDependencyInjectionAspect {
|
||||||
* Select least specific super type that is marked for DI (so that injection occurs only once with pre-construction inejection
|
* Select least specific super type that is marked for DI (so that injection occurs only once with pre-construction inejection
|
||||||
*/
|
*/
|
||||||
public abstract pointcut leastSpecificSuperTypeConstruction();
|
public abstract pointcut leastSpecificSuperTypeConstruction();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the bean
|
* Configure the bean
|
||||||
*/
|
*/
|
||||||
public abstract void configureBean(Object bean);
|
public abstract void configureBean(Object bean);
|
||||||
|
|
||||||
|
|
||||||
private pointcut preConstructionCondition() :
|
private pointcut preConstructionCondition() :
|
||||||
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
|
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
|
||||||
|
|
||||||
private pointcut postConstructionCondition() :
|
private pointcut postConstructionCondition() :
|
||||||
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
|
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Pre-construction configuration.
|
* Pre-construction configuration.
|
||||||
*/
|
*/
|
||||||
@SuppressAjWarnings("adviceDidNotMatch")
|
@SuppressAjWarnings("adviceDidNotMatch")
|
||||||
before(Object bean) :
|
before(Object bean) :
|
||||||
beanConstruction(bean) && preConstructionCondition() && inConfigurableBean() {
|
beanConstruction(bean) && preConstructionCondition() && inConfigurableBean() {
|
||||||
configureBean(bean);
|
configureBean(bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -84,18 +84,18 @@ public abstract aspect AbstractDependencyInjectionAspect {
|
||||||
* Post-construction configuration.
|
* Post-construction configuration.
|
||||||
*/
|
*/
|
||||||
@SuppressAjWarnings("adviceDidNotMatch")
|
@SuppressAjWarnings("adviceDidNotMatch")
|
||||||
after(Object bean) returning :
|
after(Object bean) returning :
|
||||||
beanConstruction(bean) && postConstructionCondition() && inConfigurableBean() {
|
beanConstruction(bean) && postConstructionCondition() && inConfigurableBean() {
|
||||||
configureBean(bean);
|
configureBean(bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Post-deserialization configuration.
|
* Post-deserialization configuration.
|
||||||
*/
|
*/
|
||||||
@SuppressAjWarnings("adviceDidNotMatch")
|
@SuppressAjWarnings("adviceDidNotMatch")
|
||||||
after(Object bean) returning :
|
after(Object bean) returning :
|
||||||
beanDeserialization(bean) && inConfigurableBean() {
|
beanDeserialization(bean) && inConfigurableBean() {
|
||||||
configureBean(bean);
|
configureBean(bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -26,36 +26,36 @@ import java.io.Serializable;
|
||||||
* upon deserialization. Subaspects need to simply provide definition for the configureBean() method. This
|
* upon deserialization. Subaspects need to simply provide definition for the configureBean() method. This
|
||||||
* method may be implemented without relying on Spring container if so desired.
|
* method may be implemented without relying on Spring container if so desired.
|
||||||
* </p>
|
* </p>
|
||||||
* <p>
|
* <p>
|
||||||
* There are two cases that needs to be handled:
|
* There are two cases that needs to be handled:
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>Normal object creation via the '{@code new}' operator: this is
|
* <li>Normal object creation via the '<code>new</code>' operator: this is
|
||||||
* taken care of by advising {@code initialization()} join points.</li>
|
* taken care of by advising <code>initialization()</code> join points.</li>
|
||||||
* <li>Object creation through deserialization: since no constructor is
|
* <li>Object creation through deserialization: since no constructor is
|
||||||
* invoked during deserialization, the aspect needs to advise a method that a
|
* invoked during deserialization, the aspect needs to advise a method that a
|
||||||
* deserialization mechanism is going to invoke. Ideally, we should not
|
* deserialization mechanism is going to invoke. Ideally, we should not
|
||||||
* require user classes to implement any specific method. This implies that
|
* require user classes to implement any specific method. This implies that
|
||||||
* we need to <i>introduce</i> the chosen method. We should also handle the cases
|
* we need to <i>introduce</i> the chosen method. We should also handle the cases
|
||||||
* where the chosen method is already implemented in classes (in which case,
|
* where the chosen method is already implemented in classes (in which case,
|
||||||
* the user's implementation for that method should take precedence over the
|
* the user's implementation for that method should take precedence over the
|
||||||
* introduced implementation). There are a few choices for the chosen method:
|
* introduced implementation). There are a few choices for the chosen method:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>readObject(ObjectOutputStream): Java requires that the method must be
|
* <li>readObject(ObjectOutputStream): Java requires that the method must be
|
||||||
* {@code private}. Since aspects cannot introduce a private member,
|
* <code>private</p>. Since aspects cannot introduce a private member,
|
||||||
* while preserving its name, this option is ruled out.</li>
|
* while preserving its name, this option is ruled out.</li>
|
||||||
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
|
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
|
||||||
* Problem solved! There is one (minor) limitation of this approach in
|
* Problem solved! There is one (minor) limitation of this approach in
|
||||||
* that if a user class already has this method, that method must be
|
* that if a user class already has this method, that method must be
|
||||||
* {@code public}. However, this shouldn't be a big burden, since
|
* <code>public</code>. However, this shouldn't be a big burden, since
|
||||||
* use cases that need classes to implement readResolve() (custom enums,
|
* use cases that need classes to implement readResolve() (custom enums,
|
||||||
* for example) are unlikely to be marked as @Configurable, and
|
* for example) are unlikely to be marked as @Configurable, and
|
||||||
* in any case asking to make that method {@code public} should not
|
* in any case asking to make that method <code>public</code> should not
|
||||||
* pose any undue burden.</li>
|
* pose any undue burden.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
* The minor collaboration needed by user classes (i.e., that the
|
* The minor collaboration needed by user classes (i.e., that the
|
||||||
* implementation of {@code readResolve()}, if any, must be
|
* implementation of <code>readResolve()</code>, if any, must be
|
||||||
* {@code public}) can be lifted as well if we were to use an
|
* <code>public</code>) can be lifted as well if we were to use an
|
||||||
* experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
|
* experimental feature in AspectJ - the <code>hasmethod()</code> PCD.</li>
|
||||||
* </ol>
|
* </ol>
|
||||||
|
|
||||||
* <p>
|
* <p>
|
||||||
|
|
@ -63,7 +63,7 @@ import java.io.Serializable;
|
||||||
* is to use a 'declare parents' statement another aspect (a subaspect of this aspect would be a logical choice)
|
* is to use a 'declare parents' statement another aspect (a subaspect of this aspect would be a logical choice)
|
||||||
* that declares the classes that need to be configured by supplying the {@link ConfigurableObject} interface.
|
* that declares the classes that need to be configured by supplying the {@link ConfigurableObject} interface.
|
||||||
* </p>
|
* </p>
|
||||||
*
|
*
|
||||||
* @author Ramnivas Laddad
|
* @author Ramnivas Laddad
|
||||||
* @since 2.5.2
|
* @since 2.5.2
|
||||||
*/
|
*/
|
||||||
|
|
@ -71,8 +71,8 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
|
||||||
/**
|
/**
|
||||||
* Select initialization join point as object construction
|
* Select initialization join point as object construction
|
||||||
*/
|
*/
|
||||||
public pointcut beanConstruction(Object bean) :
|
public pointcut beanConstruction(Object bean) :
|
||||||
initialization(ConfigurableObject+.new(..)) && this(bean);
|
initialization(ConfigurableObject+.new(..)) && this(bean);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport
|
* Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport
|
||||||
|
|
@ -80,40 +80,40 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
|
||||||
public pointcut beanDeserialization(Object bean) :
|
public pointcut beanDeserialization(Object bean) :
|
||||||
execution(Object ConfigurableDeserializationSupport+.readResolve()) &&
|
execution(Object ConfigurableDeserializationSupport+.readResolve()) &&
|
||||||
this(bean);
|
this(bean);
|
||||||
|
|
||||||
public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..));
|
public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Implementation to support re-injecting dependencies once an object is deserialized
|
// Implementation to support re-injecting dependencies once an object is deserialized
|
||||||
/**
|
/**
|
||||||
* Declare any class implementing Serializable and ConfigurableObject as also implementing
|
* Declare any class implementing Serializable and ConfigurableObject as also implementing
|
||||||
* ConfigurableDeserializationSupport. This allows us to introduce the readResolve()
|
* ConfigurableDeserializationSupport. This allows us to introduce the readResolve()
|
||||||
* method and select it with the beanDeserialization() pointcut.
|
* method and select it with the beanDeserialization() pointcut.
|
||||||
*
|
*
|
||||||
* <p>Here is an improved version that uses the hasmethod() pointcut and lifts
|
* <p>Here is an improved version that uses the hasmethod() pointcut and lifts
|
||||||
* even the minor requirement on user classes:
|
* even the minor requirement on user classes:
|
||||||
*
|
*
|
||||||
* <pre class="code">declare parents: ConfigurableObject+ Serializable+
|
* <pre class="code">declare parents: ConfigurableObject+ Serializable+
|
||||||
* && !hasmethod(Object readResolve() throws ObjectStreamException)
|
* && !hasmethod(Object readResolve() throws ObjectStreamException)
|
||||||
* implements ConfigurableDeserializationSupport;
|
* implements ConfigurableDeserializationSupport;
|
||||||
* </pre>
|
* </pre>
|
||||||
*/
|
*/
|
||||||
declare parents:
|
declare parents:
|
||||||
ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
|
ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A marker interface to which the {@code readResolve()} is introduced.
|
* A marker interface to which the <code>readResolve()</code> is introduced.
|
||||||
*/
|
*/
|
||||||
static interface ConfigurableDeserializationSupport extends Serializable {
|
static interface ConfigurableDeserializationSupport extends Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Introduce the {@code readResolve()} method so that we can advise its
|
* Introduce the <code>readResolve()</code> method so that we can advise its
|
||||||
* execution to configure the object.
|
* execution to configure the object.
|
||||||
*
|
*
|
||||||
* <p>Note if a method with the same signature already exists in a
|
* <p>Note if a method with the same signature already exists in a
|
||||||
* {@code Serializable} class of ConfigurableObject type,
|
* <code>Serializable</code> class of ConfigurableObject type,
|
||||||
* that implementation will take precedence (a good thing, since we are
|
* that implementation will take precedence (a good thing, since we are
|
||||||
* merely interested in an opportunity to detect deserialization.)
|
* merely interested in an opportunity to detect deserialization.)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -32,7 +32,7 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||||
* annotation to identify which classes need autowiring.
|
* annotation to identify which classes need autowiring.
|
||||||
*
|
*
|
||||||
* <p>The bean name to look up will be taken from the
|
* <p>The bean name to look up will be taken from the
|
||||||
* {@code @Configurable} annotation if specified, otherwise the
|
* <code>@Configurable</code> annotation if specified, otherwise the
|
||||||
* default bean name to look up will be the FQN of the class being configured.
|
* default bean name to look up will be the FQN of the class being configured.
|
||||||
*
|
*
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
|
|
@ -43,7 +43,7 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||||
* @see org.springframework.beans.factory.annotation.Configurable
|
* @see org.springframework.beans.factory.annotation.Configurable
|
||||||
* @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
|
* @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
|
||||||
*/
|
*/
|
||||||
public aspect AnnotationBeanConfigurerAspect
|
public aspect AnnotationBeanConfigurerAspect
|
||||||
extends AbstractInterfaceDrivenDependencyInjectionAspect
|
extends AbstractInterfaceDrivenDependencyInjectionAspect
|
||||||
implements BeanFactoryAware, InitializingBean, DisposableBean {
|
implements BeanFactoryAware, InitializingBean, DisposableBean {
|
||||||
|
|
||||||
|
|
@ -51,7 +51,7 @@ public aspect AnnotationBeanConfigurerAspect
|
||||||
|
|
||||||
public pointcut inConfigurableBean() : @this(Configurable);
|
public pointcut inConfigurableBean() : @this(Configurable);
|
||||||
|
|
||||||
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
|
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
|
||||||
|
|
||||||
declare parents: @Configurable * implements ConfigurableObject;
|
declare parents: @Configurable * implements ConfigurableObject;
|
||||||
|
|
||||||
|
|
@ -80,10 +80,10 @@ public aspect AnnotationBeanConfigurerAspect
|
||||||
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if(c.preConstruction());
|
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if(c.preConstruction());
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This declaration shouldn't be needed,
|
* This declaration shouldn't be needed,
|
||||||
* except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
|
* except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
|
||||||
*/
|
*/
|
||||||
declare parents: @Configurable Serializable+
|
declare parents: @Configurable Serializable+
|
||||||
implements ConfigurableDeserializationSupport;
|
implements ConfigurableDeserializationSupport;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,38 +17,38 @@ package org.springframework.beans.factory.aspectj;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generic-based dependency injection aspect.
|
* Generic-based dependency injection aspect.
|
||||||
* <p>
|
* <p>
|
||||||
* This aspect allows users to implement efficient, type-safe dependency injection without
|
* This aspect allows users to implement efficient, type-safe dependency injection without
|
||||||
* the use of the @Configurable annotation.
|
* the use of the @Configurable annotation.
|
||||||
*
|
*
|
||||||
* The subaspect of this aspect doesn't need to include any AOP constructs.
|
* The subaspect of this aspect doesn't need to include any AOP constructs.
|
||||||
* For example, here is a subaspect that configures the {@code PricingStrategyClient} objects.
|
* For example, here is a subaspect that configures the <code>PricingStrategyClient</code> objects.
|
||||||
* <pre>
|
* <pre>
|
||||||
* aspect PricingStrategyDependencyInjectionAspect
|
* aspect PricingStrategyDependencyInjectionAspect
|
||||||
* extends GenericInterfaceDrivenDependencyInjectionAspect<PricingStrategyClient> {
|
* extends GenericInterfaceDrivenDependencyInjectionAspect<PricingStrategyClient> {
|
||||||
* private PricingStrategy pricingStrategy;
|
* private PricingStrategy pricingStrategy;
|
||||||
*
|
*
|
||||||
* public void configure(PricingStrategyClient bean) {
|
* public void configure(PricingStrategyClient bean) {
|
||||||
* bean.setPricingStrategy(pricingStrategy);
|
* bean.setPricingStrategy(pricingStrategy);
|
||||||
* }
|
|
||||||
*
|
|
||||||
* public void setPricingStrategy(PricingStrategy pricingStrategy) {
|
|
||||||
* this.pricingStrategy = pricingStrategy;
|
|
||||||
* }
|
* }
|
||||||
|
*
|
||||||
|
* public void setPricingStrategy(PricingStrategy pricingStrategy) {
|
||||||
|
* this.pricingStrategy = pricingStrategy;
|
||||||
|
* }
|
||||||
* }
|
* }
|
||||||
* </pre>
|
* </pre>
|
||||||
* @author Ramnivas Laddad
|
* @author Ramnivas Laddad
|
||||||
* @since 3.0.0
|
* @since 3.0.0
|
||||||
*/
|
*/
|
||||||
public abstract aspect GenericInterfaceDrivenDependencyInjectionAspect<I> extends AbstractInterfaceDrivenDependencyInjectionAspect {
|
public abstract aspect GenericInterfaceDrivenDependencyInjectionAspect<I> extends AbstractInterfaceDrivenDependencyInjectionAspect {
|
||||||
declare parents: I implements ConfigurableObject;
|
declare parents: I implements ConfigurableObject;
|
||||||
|
|
||||||
public pointcut inConfigurableBean() : within(I+);
|
public pointcut inConfigurableBean() : within(I+);
|
||||||
|
|
||||||
public final void configureBean(Object bean) {
|
public final void configureBean(Object bean) {
|
||||||
configure((I)bean);
|
configure((I)bean);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unfortunately, erasure used with generics won't allow to use the same named method
|
// Unfortunately, erasure used with generics won't allow to use the same named method
|
||||||
protected abstract void configure(I bean);
|
protected abstract void configure(I bean);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -62,7 +62,7 @@ public abstract aspect AbstractCacheAspect extends CacheAspectSupport {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return execute(aspectJInvoker, thisJoinPoint.getTarget(), method, thisJoinPoint.getArgs());
|
return execute(aspectJInvoker, thisJoinPoint.getTarget(), method, thisJoinPoint.getArgs());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -23,9 +23,9 @@ import java.util.List;
|
||||||
/**
|
/**
|
||||||
* Abstract aspect to enable mocking of methods picked out by a pointcut.
|
* Abstract aspect to enable mocking of methods picked out by a pointcut.
|
||||||
* Sub-aspects must define the mockStaticsTestMethod() pointcut to
|
* Sub-aspects must define the mockStaticsTestMethod() pointcut to
|
||||||
* indicate call stacks when mocking should be triggered, and the
|
* indicate call stacks when mocking should be triggered, and the
|
||||||
* methodToMock() pointcut to pick out a method invocations to mock.
|
* methodToMock() pointcut to pick out a method invocations to mock.
|
||||||
*
|
*
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
* @author Ramnivas Laddad
|
* @author Ramnivas Laddad
|
||||||
*/
|
*/
|
||||||
|
|
@ -42,7 +42,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||||
// Represents a list of expected calls to static entity methods
|
// Represents a list of expected calls to static entity methods
|
||||||
// Public to allow inserted code to access: is this normal??
|
// Public to allow inserted code to access: is this normal??
|
||||||
public class Expectations {
|
public class Expectations {
|
||||||
|
|
||||||
// Represents an expected call to a static entity method
|
// Represents an expected call to a static entity method
|
||||||
private class Call {
|
private class Call {
|
||||||
private final String signature;
|
private final String signature;
|
||||||
|
|
@ -50,21 +50,21 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||||
|
|
||||||
private Object responseObject; // return value or throwable
|
private Object responseObject; // return value or throwable
|
||||||
private CallResponse responseType = CallResponse.nothing;
|
private CallResponse responseType = CallResponse.nothing;
|
||||||
|
|
||||||
public Call(String name, Object[] args) {
|
public Call(String name, Object[] args) {
|
||||||
this.signature = name;
|
this.signature = name;
|
||||||
this.args = args;
|
this.args = args;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean hasResponseSpecified() {
|
public boolean hasResponseSpecified() {
|
||||||
return responseType != CallResponse.nothing;
|
return responseType != CallResponse.nothing;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReturnVal(Object retVal) {
|
public void setReturnVal(Object retVal) {
|
||||||
this.responseObject = retVal;
|
this.responseObject = retVal;
|
||||||
responseType = CallResponse.return_;
|
responseType = CallResponse.return_;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setThrow(Throwable throwable) {
|
public void setThrow(Throwable throwable) {
|
||||||
this.responseObject = throwable;
|
this.responseObject = throwable;
|
||||||
responseType = CallResponse.throw_;
|
responseType = CallResponse.throw_;
|
||||||
|
|
@ -89,7 +89,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private List<Call> calls = new LinkedList<Call>();
|
private List<Call> calls = new LinkedList<Call>();
|
||||||
|
|
||||||
// Calls already verified
|
// Calls already verified
|
||||||
|
|
@ -101,12 +101,12 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||||
+ " calls, received " + verified);
|
+ " calls, received " + verified);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Validate the call and provide the expected return value
|
* Validate the call and provide the expected return value
|
||||||
* @param lastSig
|
* @param lastSig
|
||||||
* @param args
|
* @param args
|
||||||
* @return the return value
|
* @return
|
||||||
*/
|
*/
|
||||||
public Object respond(String lastSig, Object[] args) {
|
public Object respond(String lastSig, Object[] args) {
|
||||||
Call call = nextCall();
|
Call call = nextCall();
|
||||||
|
|
@ -114,7 +114,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||||
if (responseType == CallResponse.return_) {
|
if (responseType == CallResponse.return_) {
|
||||||
return call.returnValue(lastSig, args);
|
return call.returnValue(lastSig, args);
|
||||||
} else if(responseType == CallResponse.throw_) {
|
} else if(responseType == CallResponse.throw_) {
|
||||||
return call.throwException(lastSig, args);
|
return (RuntimeException)call.throwException(lastSig, args);
|
||||||
} else if(responseType == CallResponse.nothing) {
|
} else if(responseType == CallResponse.nothing) {
|
||||||
// do nothing
|
// do nothing
|
||||||
}
|
}
|
||||||
|
|
@ -175,7 +175,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||||
return expectations.respond(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
return expectations.respond(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void expectReturnInternal(Object retVal) {
|
public void expectReturnInternal(Object retVal) {
|
||||||
if (!recording) {
|
if (!recording) {
|
||||||
throw new IllegalStateException("Not recording: Cannot set return value");
|
throw new IllegalStateException("Not recording: Cannot set return value");
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -18,16 +18,16 @@ package org.springframework.mock.staticmock;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Annotation-based aspect to use in test build to enable mocking static methods
|
* Annotation-based aspect to use in test build to enable mocking static methods
|
||||||
* on JPA-annotated {@code @Entity} classes, as used by Roo for finders.
|
* on JPA-annotated <code>@Entity</code> classes, as used by Roo for finders.
|
||||||
*
|
*
|
||||||
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
|
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
|
||||||
* that is annotated with the @MockStaticEntityMethods annotation.
|
* that is annotated with the @MockStaticEntityMethods annotation.
|
||||||
*
|
*
|
||||||
* <p>Also provides static methods to simplify the programming model for
|
* <p>Also provides static methods to simplify the programming model for
|
||||||
* entering playback mode and setting expected return values.
|
* entering playback mode and setting expected return values.
|
||||||
*
|
*
|
||||||
* <p>Usage:
|
* <p>Usage:
|
||||||
* <ol>
|
* <ol>
|
||||||
* <li>Annotate a test class with @MockStaticEntityMethods.
|
* <li>Annotate a test class with @MockStaticEntityMethods.
|
||||||
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
|
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
|
||||||
* Invoke static methods on Entity classes, with each recording-mode invocation
|
* Invoke static methods on Entity classes, with each recording-mode invocation
|
||||||
|
|
@ -37,20 +37,20 @@ package org.springframework.mock.staticmock;
|
||||||
* <li>Call the code you wish to test that uses the static methods. Verification will
|
* <li>Call the code you wish to test that uses the static methods. Verification will
|
||||||
* occur automatically.
|
* occur automatically.
|
||||||
* </ol>
|
* </ol>
|
||||||
*
|
*
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
* @author Ramnivas Laddad
|
* @author Ramnivas Laddad
|
||||||
* @see MockStaticEntityMethods
|
* @see MockStaticEntityMethods
|
||||||
*/
|
*/
|
||||||
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Stop recording mock calls and enter playback state
|
* Stop recording mock calls and enter playback state
|
||||||
*/
|
*/
|
||||||
public static void playback() {
|
public static void playback() {
|
||||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal();
|
AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void expectReturn(Object retVal) {
|
public static void expectReturn(Object retVal) {
|
||||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal);
|
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,19 +1,3 @@
|
||||||
/*
|
|
||||||
* Copyright 2002-2012 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.orm.jpa.aspectj;
|
package org.springframework.orm.jpa.aspectj;
|
||||||
|
|
||||||
import javax.persistence.EntityManager;
|
import javax.persistence.EntityManager;
|
||||||
|
|
@ -25,14 +9,14 @@ import org.springframework.dao.DataAccessException;
|
||||||
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
|
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
|
||||||
|
|
||||||
public aspect JpaExceptionTranslatorAspect {
|
public aspect JpaExceptionTranslatorAspect {
|
||||||
pointcut entityManagerCall(): call(* EntityManager.*(..)) || call(* EntityManagerFactory.*(..)) || call(* EntityTransaction.*(..)) || call(* Query.*(..));
|
pointcut entityManagerCall(): call(* EntityManager.*(..)) || call(* EntityManagerFactory.*(..)) || call(* EntityTransaction.*(..)) || call(* Query.*(..));
|
||||||
|
|
||||||
after() throwing(RuntimeException re): entityManagerCall() {
|
after() throwing(RuntimeException re): entityManagerCall() {
|
||||||
DataAccessException dex = EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(re);
|
DataAccessException dex = EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(re);
|
||||||
if (dex != null) {
|
if (dex != null) {
|
||||||
throw dex;
|
throw dex;
|
||||||
} else {
|
} else {
|
||||||
throw re;
|
throw re;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -28,7 +28,7 @@ import org.springframework.core.task.AsyncTaskExecutor;
|
||||||
/**
|
/**
|
||||||
* Abstract aspect that routes selected methods asynchronously.
|
* Abstract aspect that routes selected methods asynchronously.
|
||||||
*
|
*
|
||||||
* <p>This aspect needs to be injected with an implementation of
|
* <p>This aspect needs to be injected with an implementation of
|
||||||
* {@link Executor} to activate it for a specific thread pool.
|
* {@link Executor} to activate it for a specific thread pool.
|
||||||
* Otherwise it will simply delegate all calls synchronously.
|
* Otherwise it will simply delegate all calls synchronously.
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -25,7 +25,7 @@ import org.springframework.transaction.interceptor.TransactionAttributeSource;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract superaspect for AspectJ transaction aspects. Concrete
|
* Abstract superaspect for AspectJ transaction aspects. Concrete
|
||||||
* subaspects will implement the {@code transactionalMethodExecution()}
|
* subaspects will implement the <code>transactionalMethodExecution()</code>
|
||||||
* pointcut using a strategy such as Java 5 annotations.
|
* pointcut using a strategy such as Java 5 annotations.
|
||||||
*
|
*
|
||||||
* <p>Suitable for use inside or outside the Spring IoC container.
|
* <p>Suitable for use inside or outside the Spring IoC container.
|
||||||
|
|
@ -66,7 +66,7 @@ public abstract aspect AbstractTransactionAspect extends TransactionAspectSuppor
|
||||||
@SuppressAjWarnings("adviceDidNotMatch")
|
@SuppressAjWarnings("adviceDidNotMatch")
|
||||||
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
|
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
|
||||||
try {
|
try {
|
||||||
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
|
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
|
||||||
}
|
}
|
||||||
catch (Throwable t2) {
|
catch (Throwable t2) {
|
||||||
logger.error("Failed to close transaction after throwing in a transactional method", t2);
|
logger.error("Failed to close transaction after throwing in a transactional method", t2);
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -21,17 +21,17 @@ import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete AspectJ transaction aspect using Spring's @Transactional annotation.
|
* Concrete AspectJ transaction aspect using Spring's @Transactional annotation.
|
||||||
*
|
*
|
||||||
* <p>When using this aspect, you <i>must</i> annotate the implementation class
|
* <p>When using this aspect, you <i>must</i> annotate the implementation class
|
||||||
* (and/or methods within that class), <i>not</i> the interface (if any) that
|
* (and/or methods within that class), <i>not</i> the interface (if any) that
|
||||||
* the class implements. AspectJ follows Java's rule that annotations on
|
* the class implements. AspectJ follows Java's rule that annotations on
|
||||||
* interfaces are <i>not</i> inherited.
|
* interfaces are <i>not</i> inherited.
|
||||||
*
|
*
|
||||||
* <p>An @Transactional annotation on a class specifies the default transaction
|
* <p>An @Transactional annotation on a class specifies the default transaction
|
||||||
* semantics for the execution of any <b>public</b> operation in the class.
|
* semantics for the execution of any <b>public</b> operation in the class.
|
||||||
*
|
*
|
||||||
* <p>An @Transactional annotation on a method within the class overrides the
|
* <p>An @Transactional annotation on a method within the class overrides the
|
||||||
* default transaction semantics given by the class annotation (if present).
|
* default transaction semantics given by the class annotation (if present).
|
||||||
* Any method may be annotated (regardless of visibility).
|
* Any method may be annotated (regardless of visibility).
|
||||||
* Annotating non-public methods directly is the only way
|
* Annotating non-public methods directly is the only way
|
||||||
* to get transaction demarcation for the execution of such operations.
|
* to get transaction demarcation for the execution of such operations.
|
||||||
|
|
@ -57,7 +57,7 @@ public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
|
||||||
execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
|
execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches the execution of any method with the
|
* Matches the execution of any method with the
|
||||||
* Transactional annotation.
|
* Transactional annotation.
|
||||||
*/
|
*/
|
||||||
private pointcut executionOfTransactionalMethod() :
|
private pointcut executionOfTransactionalMethod() :
|
||||||
|
|
@ -66,7 +66,7 @@ public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
|
||||||
/**
|
/**
|
||||||
* Definition of pointcut from super aspect - matched join points
|
* Definition of pointcut from super aspect - matched join points
|
||||||
* will have Spring transaction management applied.
|
* will have Spring transaction management applied.
|
||||||
*/
|
*/
|
||||||
protected pointcut transactionalMethodExecution(Object txObject) :
|
protected pointcut transactionalMethodExecution(Object txObject) :
|
||||||
(executionOfAnyPublicMethodInAtTransactionalType()
|
(executionOfAnyPublicMethodInAtTransactionalType()
|
||||||
|| executionOfTransactionalMethod() )
|
|| executionOfTransactionalMethod() )
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -107,9 +107,6 @@ public class CachedIntrospectionResults {
|
||||||
* @param classLoader the ClassLoader to clear the cache for
|
* @param classLoader the ClassLoader to clear the cache for
|
||||||
*/
|
*/
|
||||||
public static void clearClassLoader(ClassLoader classLoader) {
|
public static void clearClassLoader(ClassLoader classLoader) {
|
||||||
if (classLoader == null) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
synchronized (classCache) {
|
synchronized (classCache) {
|
||||||
for (Iterator<Class> it = classCache.keySet().iterator(); it.hasNext();) {
|
for (Iterator<Class> it = classCache.keySet().iterator(); it.hasNext();) {
|
||||||
Class beanClass = it.next();
|
Class beanClass = it.next();
|
||||||
|
|
@ -199,12 +196,12 @@ public class CachedIntrospectionResults {
|
||||||
* @param parent the parent ClassLoader to check for
|
* @param parent the parent ClassLoader to check for
|
||||||
*/
|
*/
|
||||||
private static boolean isUnderneathClassLoader(ClassLoader candidate, ClassLoader parent) {
|
private static boolean isUnderneathClassLoader(ClassLoader candidate, ClassLoader parent) {
|
||||||
if (candidate == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (candidate == parent) {
|
if (candidate == parent) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if (candidate == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
ClassLoader classLoaderToCheck = candidate;
|
ClassLoader classLoaderToCheck = candidate;
|
||||||
while (classLoaderToCheck != null) {
|
while (classLoaderToCheck != null) {
|
||||||
classLoaderToCheck = classLoaderToCheck.getParent();
|
classLoaderToCheck = classLoaderToCheck.getParent();
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@ import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -116,6 +117,14 @@ class ExtendedBeanInfo implements BeanInfo {
|
||||||
matches.add(method);
|
matches.add(method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// sort non-void returning write methods to guard against the ill effects of
|
||||||
|
// non-deterministic sorting of methods returned from Class#getDeclaredMethods
|
||||||
|
// under JDK 7. See http://bugs.sun.com/view_bug.do?bug_id=7023180
|
||||||
|
Collections.sort(matches, new Comparator<Method>() {
|
||||||
|
public int compare(Method m1, Method m2) {
|
||||||
|
return m2.toString().compareTo(m1.toString());
|
||||||
|
}
|
||||||
|
});
|
||||||
return matches;
|
return matches;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -264,7 +273,7 @@ class SimpleNonIndexedPropertyDescriptor extends PropertyDescriptor {
|
||||||
public SimpleNonIndexedPropertyDescriptor(String propertyName,
|
public SimpleNonIndexedPropertyDescriptor(String propertyName,
|
||||||
Method readMethod, Method writeMethod) throws IntrospectionException {
|
Method readMethod, Method writeMethod) throws IntrospectionException {
|
||||||
|
|
||||||
super(propertyName, readMethod, writeMethod);
|
super(propertyName, null, null);
|
||||||
this.setReadMethod(readMethod);
|
this.setReadMethod(readMethod);
|
||||||
this.setWriteMethod(writeMethod);
|
this.setWriteMethod(writeMethod);
|
||||||
this.propertyType = findPropertyType(readMethod, writeMethod);
|
this.propertyType = findPropertyType(readMethod, writeMethod);
|
||||||
|
|
@ -353,7 +362,7 @@ class SimpleIndexedPropertyDescriptor extends IndexedPropertyDescriptor {
|
||||||
Method indexedReadMethod, Method indexedWriteMethod)
|
Method indexedReadMethod, Method indexedWriteMethod)
|
||||||
throws IntrospectionException {
|
throws IntrospectionException {
|
||||||
|
|
||||||
super(propertyName, readMethod, writeMethod, indexedReadMethod, indexedWriteMethod);
|
super(propertyName, null, null, null, null);
|
||||||
this.setReadMethod(readMethod);
|
this.setReadMethod(readMethod);
|
||||||
this.setWriteMethod(writeMethod);
|
this.setWriteMethod(writeMethod);
|
||||||
this.propertyType = findPropertyType(readMethod, writeMethod);
|
this.propertyType = findPropertyType(readMethod, writeMethod);
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -23,6 +23,9 @@ package org.springframework.beans;
|
||||||
* algorithm (including delegation to {@link java.beans.PropertyEditor} and
|
* algorithm (including delegation to {@link java.beans.PropertyEditor} and
|
||||||
* {@link org.springframework.core.convert.ConversionService}) underneath.
|
* {@link org.springframework.core.convert.ConversionService}) underneath.
|
||||||
*
|
*
|
||||||
|
* <p><b>Note:</b> Due to its reliance on {@link java.beans.PropertyEditor PropertyEditors},
|
||||||
|
* SimpleTypeConverter is <em>not</em> thread-safe. Use a separate instance for each thread.
|
||||||
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @see BeanWrapperImpl
|
* @see BeanWrapperImpl
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -24,6 +24,10 @@ import org.springframework.core.MethodParameter;
|
||||||
* Interface that defines type conversion methods. Typically (but not necessarily)
|
* Interface that defines type conversion methods. Typically (but not necessarily)
|
||||||
* implemented in conjunction with the {@link PropertyEditorRegistry} interface.
|
* implemented in conjunction with the {@link PropertyEditorRegistry} interface.
|
||||||
*
|
*
|
||||||
|
* <p><b>Note:</b> Since TypeConverter implementations are typically based on
|
||||||
|
* {@link java.beans.PropertyEditor PropertyEditors} which aren't thread-safe,
|
||||||
|
* TypeConverters themselves are <em>not</em> to be considered as thread-safe either.
|
||||||
|
*
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
* @see SimpleTypeConverter
|
* @see SimpleTypeConverter
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -143,7 +143,7 @@ public interface BeanFactory {
|
||||||
* is {@code Object.class}, this method will succeed whatever the class of the
|
* is {@code Object.class}, this method will succeed whatever the class of the
|
||||||
* returned instance.
|
* returned instance.
|
||||||
* @return an instance of the bean
|
* @return an instance of the bean
|
||||||
* @throws NoSuchBeanDefinitionException if there's no such bean definition
|
* @throws NoSuchBeanDefinitionException if there is no such bean definition
|
||||||
* @throws BeanNotOfRequiredTypeException if the bean is not of the required type
|
* @throws BeanNotOfRequiredTypeException if the bean is not of the required type
|
||||||
* @throws BeansException if the bean could not be created
|
* @throws BeansException if the bean could not be created
|
||||||
*/
|
*/
|
||||||
|
|
@ -158,7 +158,8 @@ public interface BeanFactory {
|
||||||
* of the given type. For more extensive retrieval operations across sets of beans,
|
* of the given type. For more extensive retrieval operations across sets of beans,
|
||||||
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
|
* use {@link ListableBeanFactory} and/or {@link BeanFactoryUtils}.
|
||||||
* @return an instance of the single bean matching the required type
|
* @return an instance of the single bean matching the required type
|
||||||
* @throws NoSuchBeanDefinitionException if there is not exactly one matching bean found
|
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||||
|
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
* @see ListableBeanFactory
|
* @see ListableBeanFactory
|
||||||
*/
|
*/
|
||||||
|
|
@ -172,7 +173,7 @@ public interface BeanFactory {
|
||||||
* @param args arguments to use if creating a prototype using explicit arguments to a
|
* @param args arguments to use if creating a prototype using explicit arguments to a
|
||||||
* static factory method. It is invalid to use a non-null args value in any other case.
|
* static factory method. It is invalid to use a non-null args value in any other case.
|
||||||
* @return an instance of the bean
|
* @return an instance of the bean
|
||||||
* @throws NoSuchBeanDefinitionException if there's no such bean definition
|
* @throws NoSuchBeanDefinitionException if there is no such bean definition
|
||||||
* @throws BeanDefinitionStoreException if arguments have been given but
|
* @throws BeanDefinitionStoreException if arguments have been given but
|
||||||
* the affected bean isn't a prototype
|
* the affected bean isn't a prototype
|
||||||
* @throws BeansException if the bean could not be created
|
* @throws BeansException if the bean could not be created
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -310,20 +310,15 @@ public abstract class BeanFactoryUtils {
|
||||||
* @param lbf the bean factory
|
* @param lbf the bean factory
|
||||||
* @param type type of bean to match
|
* @param type type of bean to match
|
||||||
* @return the matching bean instance
|
* @return the matching bean instance
|
||||||
* @throws NoSuchBeanDefinitionException
|
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||||
* if 0 or more than 1 beans of the given type were found
|
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||||
* @throws BeansException if the bean could not be created
|
* @throws BeansException if the bean could not be created
|
||||||
*/
|
*/
|
||||||
public static <T> T beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)
|
public static <T> T beanOfTypeIncludingAncestors(ListableBeanFactory lbf, Class<T> type)
|
||||||
throws BeansException {
|
throws BeansException {
|
||||||
|
|
||||||
Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type);
|
Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type);
|
||||||
if (beansOfType.size() == 1) {
|
return uniqueBean(type, beansOfType);
|
||||||
return beansOfType.values().iterator().next();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new NoSuchBeanDefinitionException(type, "expected single bean but found " + beansOfType.size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -351,8 +346,8 @@ public abstract class BeanFactoryUtils {
|
||||||
* eagerly initialized to determine their type: So be aware that passing in "true"
|
* eagerly initialized to determine their type: So be aware that passing in "true"
|
||||||
* for this flag will initialize FactoryBeans and "factory-bean" references.
|
* for this flag will initialize FactoryBeans and "factory-bean" references.
|
||||||
* @return the matching bean instance
|
* @return the matching bean instance
|
||||||
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
|
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||||
* if 0 or more than 1 beans of the given type were found
|
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||||
* @throws BeansException if the bean could not be created
|
* @throws BeansException if the bean could not be created
|
||||||
*/
|
*/
|
||||||
public static <T> T beanOfTypeIncludingAncestors(
|
public static <T> T beanOfTypeIncludingAncestors(
|
||||||
|
|
@ -360,12 +355,7 @@ public abstract class BeanFactoryUtils {
|
||||||
throws BeansException {
|
throws BeansException {
|
||||||
|
|
||||||
Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type, includeNonSingletons, allowEagerInit);
|
Map<String, T> beansOfType = beansOfTypeIncludingAncestors(lbf, type, includeNonSingletons, allowEagerInit);
|
||||||
if (beansOfType.size() == 1) {
|
return uniqueBean(type, beansOfType);
|
||||||
return beansOfType.values().iterator().next();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new NoSuchBeanDefinitionException(type, "expected single bean but found " + beansOfType.size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -380,19 +370,14 @@ public abstract class BeanFactoryUtils {
|
||||||
* @param lbf the bean factory
|
* @param lbf the bean factory
|
||||||
* @param type type of bean to match
|
* @param type type of bean to match
|
||||||
* @return the matching bean instance
|
* @return the matching bean instance
|
||||||
* @throws NoSuchBeanDefinitionException
|
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||||
* if 0 or more than 1 beans of the given type were found
|
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||||
* @throws BeansException if the bean could not be created
|
* @throws BeansException if the bean could not be created
|
||||||
*/
|
*/
|
||||||
public static <T> T beanOfType(ListableBeanFactory lbf, Class<T> type) throws BeansException {
|
public static <T> T beanOfType(ListableBeanFactory lbf, Class<T> type) throws BeansException {
|
||||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||||
Map<String, T> beansOfType = lbf.getBeansOfType(type);
|
Map<String, T> beansOfType = lbf.getBeansOfType(type);
|
||||||
if (beansOfType.size() == 1) {
|
return uniqueBean(type, beansOfType);
|
||||||
return beansOfType.values().iterator().next();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
throw new NoSuchBeanDefinitionException(type, "expected single bean but found " + beansOfType.size());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -415,8 +400,8 @@ public abstract class BeanFactoryUtils {
|
||||||
* eagerly initialized to determine their type: So be aware that passing in "true"
|
* eagerly initialized to determine their type: So be aware that passing in "true"
|
||||||
* for this flag will initialize FactoryBeans and "factory-bean" references.
|
* for this flag will initialize FactoryBeans and "factory-bean" references.
|
||||||
* @return the matching bean instance
|
* @return the matching bean instance
|
||||||
* @throws org.springframework.beans.factory.NoSuchBeanDefinitionException
|
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||||
* if 0 or more than 1 beans of the given type were found
|
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||||
* @throws BeansException if the bean could not be created
|
* @throws BeansException if the bean could not be created
|
||||||
*/
|
*/
|
||||||
public static <T> T beanOfType(
|
public static <T> T beanOfType(
|
||||||
|
|
@ -425,11 +410,27 @@ public abstract class BeanFactoryUtils {
|
||||||
|
|
||||||
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
Assert.notNull(lbf, "ListableBeanFactory must not be null");
|
||||||
Map<String, T> beansOfType = lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit);
|
Map<String, T> beansOfType = lbf.getBeansOfType(type, includeNonSingletons, allowEagerInit);
|
||||||
if (beansOfType.size() == 1) {
|
return uniqueBean(type, beansOfType);
|
||||||
return beansOfType.values().iterator().next();
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract a unique bean for the given type from the given Map of matching beans.
|
||||||
|
* @param type type of bean to match
|
||||||
|
* @param matchingBeans all matching beans found
|
||||||
|
* @return the unique bean instance
|
||||||
|
* @throws NoSuchBeanDefinitionException if no bean of the given type was found
|
||||||
|
* @throws NoUniqueBeanDefinitionException if more than one bean of the given type was found
|
||||||
|
*/
|
||||||
|
private static <T> T uniqueBean(Class<T> type, Map<String, T> matchingBeans) {
|
||||||
|
int nrFound = matchingBeans.size();
|
||||||
|
if (nrFound == 1) {
|
||||||
|
return matchingBeans.values().iterator().next();
|
||||||
|
}
|
||||||
|
else if (nrFound > 1) {
|
||||||
|
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new NoSuchBeanDefinitionException(type, "expected single bean but found " + beansOfType.size());
|
throw new NoSuchBeanDefinitionException(type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -20,11 +20,13 @@ import org.springframework.beans.BeansException;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exception thrown when a {@code BeanFactory} is asked for a bean
|
* Exception thrown when a {@code BeanFactory} is asked for a bean instance
|
||||||
* instance for which it cannot find a definition.
|
* for which it cannot find a definition.
|
||||||
*
|
*
|
||||||
* @author Rod Johnson
|
* @author Rod Johnson
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @see BeanFactory#getBean(String)
|
||||||
|
* @see BeanFactory#getBean(Class)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("serial")
|
@SuppressWarnings("serial")
|
||||||
public class NoSuchBeanDefinitionException extends BeansException {
|
public class NoSuchBeanDefinitionException extends BeansException {
|
||||||
|
|
@ -60,7 +62,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||||
* @param type required type of the missing bean
|
* @param type required type of the missing bean
|
||||||
*/
|
*/
|
||||||
public NoSuchBeanDefinitionException(Class<?> type) {
|
public NoSuchBeanDefinitionException(Class<?> type) {
|
||||||
super("No unique bean of type [" + type.getName() + "] is defined");
|
super("No qualifying bean of type [" + type.getName() + "] is defined");
|
||||||
this.beanType = type;
|
this.beanType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,7 +72,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||||
* @param message detailed message describing the problem
|
* @param message detailed message describing the problem
|
||||||
*/
|
*/
|
||||||
public NoSuchBeanDefinitionException(Class<?> type, String message) {
|
public NoSuchBeanDefinitionException(Class<?> type, String message) {
|
||||||
super("No unique bean of type [" + type.getName() + "] is defined: " + message);
|
super("No qualifying bean of type [" + type.getName() + "] is defined: " + message);
|
||||||
this.beanType = type;
|
this.beanType = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -81,7 +83,7 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||||
* @param message detailed message describing the problem
|
* @param message detailed message describing the problem
|
||||||
*/
|
*/
|
||||||
public NoSuchBeanDefinitionException(Class<?> type, String dependencyDescription, String message) {
|
public NoSuchBeanDefinitionException(Class<?> type, String dependencyDescription, String message) {
|
||||||
super("No matching bean of type [" + type.getName() + "] found for dependency" +
|
super("No qualifying bean of type [" + type.getName() + "] found for dependency" +
|
||||||
(StringUtils.hasLength(dependencyDescription) ? " [" + dependencyDescription + "]" : "") +
|
(StringUtils.hasLength(dependencyDescription) ? " [" + dependencyDescription + "]" : "") +
|
||||||
": " + message);
|
": " + message);
|
||||||
this.beanType = type;
|
this.beanType = type;
|
||||||
|
|
@ -89,19 +91,26 @@ public class NoSuchBeanDefinitionException extends BeansException {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the name of the missing bean, if it was a lookup <em>by name</em>
|
* Return the name of the missing bean, if it was a lookup <em>by name</em> that failed.
|
||||||
* that failed.
|
|
||||||
*/
|
*/
|
||||||
public String getBeanName() {
|
public String getBeanName() {
|
||||||
return this.beanName;
|
return this.beanName;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the required type of the missing bean, if it was a lookup
|
* Return the required type of the missing bean, if it was a lookup <em>by type</em> that failed.
|
||||||
* <em>by type</em> that failed.
|
|
||||||
*/
|
*/
|
||||||
public Class<?> getBeanType() {
|
public Class<?> getBeanType() {
|
||||||
return this.beanType;
|
return this.beanType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of beans found when only one matching bean was expected.
|
||||||
|
* For a regular NoSuchBeanDefinitionException, this will always be 0.
|
||||||
|
* @see NoUniqueBeanDefinitionException
|
||||||
|
*/
|
||||||
|
public int getNumberOfBeansFound() {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,79 @@
|
||||||
|
/*
|
||||||
|
* 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.beans.factory;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
|
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Exception thrown when a {@code BeanFactory} is asked for a bean instance for which
|
||||||
|
* multiple matching candidates have been found when only one matching bean was expected.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.2.1
|
||||||
|
* @see BeanFactory#getBean(Class)
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("serial")
|
||||||
|
public class NoUniqueBeanDefinitionException extends NoSuchBeanDefinitionException {
|
||||||
|
|
||||||
|
private int numberOfBeansFound;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code NoUniqueBeanDefinitionException}.
|
||||||
|
* @param type required type of the non-unique bean
|
||||||
|
* @param numberOfBeansFound the number of matching beans
|
||||||
|
* @param message detailed message describing the problem
|
||||||
|
*/
|
||||||
|
public NoUniqueBeanDefinitionException(Class<?> type, int numberOfBeansFound, String message) {
|
||||||
|
super(type, message);
|
||||||
|
this.numberOfBeansFound = numberOfBeansFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code NoUniqueBeanDefinitionException}.
|
||||||
|
* @param type required type of the non-unique bean
|
||||||
|
* @param beanNamesFound the names of all matching beans (as a Collection)
|
||||||
|
*/
|
||||||
|
public NoUniqueBeanDefinitionException(Class<?> type, Collection<String> beanNamesFound) {
|
||||||
|
this(type, beanNamesFound.size(), "expected single matching bean but found " + beanNamesFound.size() + ": " +
|
||||||
|
StringUtils.collectionToCommaDelimitedString(beanNamesFound));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code NoUniqueBeanDefinitionException}.
|
||||||
|
* @param type required type of the non-unique bean
|
||||||
|
* @param beanNamesFound the names of all matching beans (as an array)
|
||||||
|
*/
|
||||||
|
public NoUniqueBeanDefinitionException(Class<?> type, String... beanNamesFound) {
|
||||||
|
this(type, Arrays.asList(beanNamesFound));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the number of beans found when only one matching bean was expected.
|
||||||
|
* For a NoUniqueBeanDefinitionException, this will usually be higher than 1.
|
||||||
|
* @see #getBeanType()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public int getNumberOfBeansFound() {
|
||||||
|
return this.numberOfBeansFound;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,7 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.beans.factory.access;
|
package org.springframework.beans.factory.access;
|
||||||
|
|
||||||
import org.springframework.beans.FatalBeanException;
|
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -49,11 +48,10 @@ public interface BeanFactoryReference {
|
||||||
* <p>In an EJB usage scenario this would normally be called from
|
* <p>In an EJB usage scenario this would normally be called from
|
||||||
* {@code ejbRemove()} and {@code ejbPassivate()}.
|
* {@code ejbRemove()} and {@code ejbPassivate()}.
|
||||||
* <p>This is safe to call multiple times.
|
* <p>This is safe to call multiple times.
|
||||||
* @throws FatalBeanException if the {@code BeanFactory} cannot be released
|
|
||||||
* @see BeanFactoryLocator
|
* @see BeanFactoryLocator
|
||||||
* @see org.springframework.context.access.ContextBeanFactoryReference
|
* @see org.springframework.context.access.ContextBeanFactoryReference
|
||||||
* @see org.springframework.context.ConfigurableApplicationContext#close()
|
* @see org.springframework.context.ConfigurableApplicationContext#close()
|
||||||
*/
|
*/
|
||||||
void release() throws FatalBeanException;
|
void release();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -27,7 +27,6 @@ import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.FatalBeanException;
|
import org.springframework.beans.FatalBeanException;
|
||||||
import org.springframework.beans.factory.BeanFactory;
|
import org.springframework.beans.factory.BeanFactory;
|
||||||
import org.springframework.beans.factory.BeanFactoryAware;
|
import org.springframework.beans.factory.BeanFactoryAware;
|
||||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.beans.factory.ListableBeanFactory;
|
import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
|
|
@ -364,12 +363,12 @@ public class ServiceLocatorFactoryBean implements FactoryBean<Object>, BeanFacto
|
||||||
try {
|
try {
|
||||||
String beanName = tryGetBeanName(args);
|
String beanName = tryGetBeanName(args);
|
||||||
if (StringUtils.hasLength(beanName)) {
|
if (StringUtils.hasLength(beanName)) {
|
||||||
// Service locator for a specific bean name.
|
// Service locator for a specific bean name
|
||||||
return beanFactory.getBean(beanName, serviceLocatorMethodReturnType);
|
return beanFactory.getBean(beanName, serviceLocatorMethodReturnType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// Service locator for a bean type.
|
// Service locator for a bean type
|
||||||
return BeanFactoryUtils.beanOfTypeIncludingAncestors(beanFactory, serviceLocatorMethodReturnType);
|
return beanFactory.getBean(serviceLocatorMethodReturnType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (BeansException ex) {
|
catch (BeansException ex) {
|
||||||
|
|
|
||||||
|
|
@ -746,6 +746,9 @@ public abstract class AbstractBeanFactory extends FactoryBeanRegistrySupport imp
|
||||||
public String resolveEmbeddedValue(String value) {
|
public String resolveEmbeddedValue(String value) {
|
||||||
String result = value;
|
String result = value;
|
||||||
for (StringValueResolver resolver : this.embeddedValueResolvers) {
|
for (StringValueResolver resolver : this.embeddedValueResolvers) {
|
||||||
|
if (result == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
result = resolver.resolveStringValue(result);
|
result = resolver.resolveStringValue(result);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -50,6 +50,7 @@ import org.springframework.beans.factory.BeanFactoryUtils;
|
||||||
import org.springframework.beans.factory.CannotLoadBeanClassException;
|
import org.springframework.beans.factory.CannotLoadBeanClassException;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.ObjectFactory;
|
import org.springframework.beans.factory.ObjectFactory;
|
||||||
import org.springframework.beans.factory.SmartFactoryBean;
|
import org.springframework.beans.factory.SmartFactoryBean;
|
||||||
import org.springframework.beans.factory.config.BeanDefinition;
|
import org.springframework.beans.factory.config.BeanDefinition;
|
||||||
|
|
@ -89,6 +90,7 @@ import org.springframework.util.StringUtils;
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
* @author Costin Leau
|
* @author Costin Leau
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
* @author Phillip Webb
|
||||||
* @since 16 April 2001
|
* @since 16 April 2001
|
||||||
* @see StaticListableBeanFactory
|
* @see StaticListableBeanFactory
|
||||||
* @see PropertiesBeanDefinitionReader
|
* @see PropertiesBeanDefinitionReader
|
||||||
|
|
@ -270,12 +272,28 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
if (beanNames.length == 1) {
|
if (beanNames.length == 1) {
|
||||||
return getBean(beanNames[0], requiredType);
|
return getBean(beanNames[0], requiredType);
|
||||||
}
|
}
|
||||||
else if (beanNames.length == 0 && getParentBeanFactory() != null) {
|
else if (beanNames.length > 1) {
|
||||||
|
T primaryBean = null;
|
||||||
|
for (String beanName : beanNames) {
|
||||||
|
T beanInstance = getBean(beanName, requiredType);
|
||||||
|
if (isPrimary(beanName, beanInstance)) {
|
||||||
|
if (primaryBean != null) {
|
||||||
|
throw new NoUniqueBeanDefinitionException(requiredType, beanNames.length,
|
||||||
|
"more than one 'primary' bean found of required type: " + Arrays.asList(beanNames));
|
||||||
|
}
|
||||||
|
primaryBean = beanInstance;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (primaryBean != null) {
|
||||||
|
return primaryBean;
|
||||||
|
}
|
||||||
|
throw new NoUniqueBeanDefinitionException(requiredType, beanNames);
|
||||||
|
}
|
||||||
|
else if (getParentBeanFactory() != null) {
|
||||||
return getParentBeanFactory().getBean(requiredType);
|
return getParentBeanFactory().getBean(requiredType);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new NoSuchBeanDefinitionException(requiredType, "expected single bean but found " +
|
throw new NoSuchBeanDefinitionException(requiredType);
|
||||||
beanNames.length + ": " + StringUtils.arrayToCommaDelimitedString(beanNames));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -823,8 +841,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
if (matchingBeans.size() > 1) {
|
if (matchingBeans.size() > 1) {
|
||||||
String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
|
String primaryBeanName = determinePrimaryCandidate(matchingBeans, descriptor);
|
||||||
if (primaryBeanName == null) {
|
if (primaryBeanName == null) {
|
||||||
throw new NoSuchBeanDefinitionException(type, "expected single matching bean but found " +
|
throw new NoUniqueBeanDefinitionException(type, matchingBeans.keySet());
|
||||||
matchingBeans.size() + ": " + matchingBeans.keySet());
|
|
||||||
}
|
}
|
||||||
if (autowiredBeanNames != null) {
|
if (autowiredBeanNames != null) {
|
||||||
autowiredBeanNames.add(primaryBeanName);
|
autowiredBeanNames.add(primaryBeanName);
|
||||||
|
|
@ -895,7 +912,7 @@ public class DefaultListableBeanFactory extends AbstractAutowireCapableBeanFacto
|
||||||
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
|
boolean candidateLocal = containsBeanDefinition(candidateBeanName);
|
||||||
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
|
boolean primaryLocal = containsBeanDefinition(primaryBeanName);
|
||||||
if (candidateLocal == primaryLocal) {
|
if (candidateLocal == primaryLocal) {
|
||||||
throw new NoSuchBeanDefinitionException(descriptor.getDependencyType(),
|
throw new NoUniqueBeanDefinitionException(descriptor.getDependencyType(), candidateBeans.size(),
|
||||||
"more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
|
"more than one 'primary' bean found among candidates: " + candidateBeans.keySet());
|
||||||
}
|
}
|
||||||
else if (candidateLocal && !primaryLocal) {
|
else if (candidateLocal && !primaryLocal) {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -61,6 +61,8 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
|
|
||||||
private static final String CLOSE_METHOD_NAME = "close";
|
private static final String CLOSE_METHOD_NAME = "close";
|
||||||
|
|
||||||
|
private static final String SHUTDOWN_METHOD_NAME = "shutdown";
|
||||||
|
|
||||||
private static final Log logger = LogFactory.getLog(DisposableBeanAdapter.class);
|
private static final Log logger = LogFactory.getLog(DisposableBeanAdapter.class);
|
||||||
|
|
||||||
private static Class closeableInterface;
|
private static Class closeableInterface;
|
||||||
|
|
@ -176,7 +178,12 @@ class DisposableBeanAdapter implements DisposableBean, Runnable, Serializable {
|
||||||
return bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
|
return bean.getClass().getMethod(CLOSE_METHOD_NAME).getName();
|
||||||
}
|
}
|
||||||
catch (NoSuchMethodException ex) {
|
catch (NoSuchMethodException ex) {
|
||||||
// no candidate destroy method found
|
try {
|
||||||
|
return bean.getClass().getMethod(SHUTDOWN_METHOD_NAME).getName();
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException ex2) {
|
||||||
|
// no candidate destroy method found
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -31,6 +31,7 @@ import org.springframework.beans.factory.BeanNotOfRequiredTypeException;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.ListableBeanFactory;
|
import org.springframework.beans.factory.ListableBeanFactory;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
|
import org.springframework.beans.factory.NoUniqueBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.SmartFactoryBean;
|
import org.springframework.beans.factory.SmartFactoryBean;
|
||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
@ -117,8 +118,11 @@ public class StaticListableBeanFactory implements ListableBeanFactory {
|
||||||
if (beanNames.length == 1) {
|
if (beanNames.length == 1) {
|
||||||
return getBean(beanNames[0], requiredType);
|
return getBean(beanNames[0], requiredType);
|
||||||
}
|
}
|
||||||
|
else if (beanNames.length > 1) {
|
||||||
|
throw new NoUniqueBeanDefinitionException(requiredType, beanNames);
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
throw new NoSuchBeanDefinitionException(requiredType, "expected single bean but found " + beanNames.length);
|
throw new NoSuchBeanDefinitionException(requiredType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -18,9 +18,8 @@ package org.springframework.beans;
|
||||||
|
|
||||||
import java.beans.BeanInfo;
|
import java.beans.BeanInfo;
|
||||||
import java.beans.PropertyDescriptor;
|
import java.beans.PropertyDescriptor;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.core.OverridingClassLoader;
|
import org.springframework.core.OverridingClassLoader;
|
||||||
|
|
@ -37,7 +36,7 @@ import static org.junit.Assert.*;
|
||||||
public final class CachedIntrospectionResultsTests {
|
public final class CachedIntrospectionResultsTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void acceptClassLoader() throws Exception {
|
public void acceptAndClearClassLoader() throws Exception {
|
||||||
BeanWrapper bw = new BeanWrapperImpl(TestBean.class);
|
BeanWrapper bw = new BeanWrapperImpl(TestBean.class);
|
||||||
assertTrue(bw.isWritableProperty("name"));
|
assertTrue(bw.isWritableProperty("name"));
|
||||||
assertTrue(bw.isWritableProperty("age"));
|
assertTrue(bw.isWritableProperty("age"));
|
||||||
|
|
@ -57,6 +56,14 @@ public final class CachedIntrospectionResultsTests {
|
||||||
assertTrue(CachedIntrospectionResults.classCache.containsKey(TestBean.class));
|
assertTrue(CachedIntrospectionResults.classCache.containsKey(TestBean.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void clearClassLoaderForSystemClassLoader() throws Exception {
|
||||||
|
BeanUtils.getPropertyDescriptors(ArrayList.class);
|
||||||
|
assertTrue(CachedIntrospectionResults.classCache.containsKey(ArrayList.class));
|
||||||
|
CachedIntrospectionResults.clearClassLoader(ArrayList.class.getClassLoader());
|
||||||
|
assertFalse(CachedIntrospectionResults.classCache.containsKey(ArrayList.class));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void shouldUseExtendedBeanInfoWhenApplicable() throws NoSuchMethodException, SecurityException {
|
public void shouldUseExtendedBeanInfoWhenApplicable() throws NoSuchMethodException, SecurityException {
|
||||||
// given a class with a non-void returning setter method
|
// given a class with a non-void returning setter method
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,7 @@ import java.beans.Introspector;
|
||||||
import java.beans.PropertyDescriptor;
|
import java.beans.PropertyDescriptor;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
@ -192,7 +193,6 @@ public class ExtendedBeanInfoTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
class Child extends Parent {
|
class Child extends Parent {
|
||||||
@Override
|
|
||||||
public Integer getProperty1() {
|
public Integer getProperty1() {
|
||||||
return 2;
|
return 2;
|
||||||
}
|
}
|
||||||
|
|
@ -214,7 +214,6 @@ public class ExtendedBeanInfoTests {
|
||||||
@Test
|
@Test
|
||||||
public void cornerSpr9453() throws IntrospectionException {
|
public void cornerSpr9453() throws IntrospectionException {
|
||||||
final class Bean implements Spr9453<Class<?>> {
|
final class Bean implements Spr9453<Class<?>> {
|
||||||
@Override
|
|
||||||
public Class<?> getProp() {
|
public Class<?> getProp() {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -583,6 +582,20 @@ public class ExtendedBeanInfoTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prior to SPR-10111 (a follow-up fix for SPR-9702), this method would throw an
|
||||||
|
* IntrospectionException regarding a "type mismatch between indexed and non-indexed
|
||||||
|
* methods" intermittently (approximately one out of every four times) under JDK 7
|
||||||
|
* due to non-deterministic results from {@link Class#getDeclaredMethods()}.
|
||||||
|
* See http://bugs.sun.com/view_bug.do?bug_id=7023180
|
||||||
|
* @see #cornerSpr9702()
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void cornerSpr10111() throws Exception {
|
||||||
|
new ExtendedBeanInfo(Introspector.getBeanInfo(BigDecimal.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void subclassWriteMethodWithCovariantReturnType() throws IntrospectionException {
|
public void subclassWriteMethodWithCovariantReturnType() throws IntrospectionException {
|
||||||
@SuppressWarnings("unused") class B {
|
@SuppressWarnings("unused") class B {
|
||||||
|
|
@ -590,9 +603,7 @@ public class ExtendedBeanInfoTests {
|
||||||
public Number setFoo(String foo) { return null; }
|
public Number setFoo(String foo) { return null; }
|
||||||
}
|
}
|
||||||
class C extends B {
|
class C extends B {
|
||||||
@Override
|
|
||||||
public String getFoo() { return null; }
|
public String getFoo() { return null; }
|
||||||
@Override
|
|
||||||
public Integer setFoo(String foo) { return null; }
|
public Integer setFoo(String foo) { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -695,7 +706,7 @@ public class ExtendedBeanInfoTests {
|
||||||
|
|
||||||
for (PropertyDescriptor pd : ebi.getPropertyDescriptors()) {
|
for (PropertyDescriptor pd : ebi.getPropertyDescriptors()) {
|
||||||
if (pd.getName().equals("foo")) {
|
if (pd.getName().equals("foo")) {
|
||||||
assertThat(pd.getWriteMethod(), is(C.class.getMethod("setFoo", int.class)));
|
assertThat(pd.getWriteMethod(), is(C.class.getMethod("setFoo", String.class)));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -733,7 +744,7 @@ public class ExtendedBeanInfoTests {
|
||||||
assertThat(hasReadMethodForProperty(ebi, "dateFormat"), is(false));
|
assertThat(hasReadMethodForProperty(ebi, "dateFormat"), is(false));
|
||||||
assertThat(hasWriteMethodForProperty(ebi, "dateFormat"), is(true));
|
assertThat(hasWriteMethodForProperty(ebi, "dateFormat"), is(true));
|
||||||
assertThat(hasIndexedReadMethodForProperty(ebi, "dateFormat"), is(false));
|
assertThat(hasIndexedReadMethodForProperty(ebi, "dateFormat"), is(false));
|
||||||
assertThat(hasIndexedWriteMethodForProperty(ebi, "dateFormat"), is(true));
|
assertThat(hasIndexedWriteMethodForProperty(ebi, "dateFormat"), is(trueUntilJdk17()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -864,7 +875,6 @@ public class ExtendedBeanInfoTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
interface TextBookOperations extends BookOperations {
|
interface TextBookOperations extends BookOperations {
|
||||||
@Override
|
|
||||||
TextBook getBook();
|
TextBook getBook();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -874,7 +884,6 @@ public class ExtendedBeanInfoTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
class LawLibrary extends Library implements TextBookOperations {
|
class LawLibrary extends Library implements TextBookOperations {
|
||||||
@Override
|
|
||||||
public LawBook getBook() { return null; }
|
public LawBook getBook() { return null; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -889,7 +898,6 @@ public class ExtendedBeanInfoTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
class B extends A {
|
class B extends A {
|
||||||
@Override
|
|
||||||
public boolean isTargetMethod() {
|
public boolean isTargetMethod() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,8 @@
|
||||||
package org.springframework.beans.factory;
|
package org.springframework.beans.factory;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.hamcrest.Matchers.containsString;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertNotNull;
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
@ -26,6 +28,11 @@ import static org.junit.Assert.assertSame;
|
||||||
import static org.junit.Assert.assertThat;
|
import static org.junit.Assert.assertThat;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
import static org.junit.Assert.fail;
|
import static org.junit.Assert.fail;
|
||||||
|
import static org.mockito.BDDMockito.given;
|
||||||
|
import static org.mockito.Matchers.isNull;
|
||||||
|
import static org.mockito.Mockito.mock;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
|
@ -49,7 +56,9 @@ import javax.security.auth.Subject;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
|
import org.junit.Rule;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.junit.rules.ExpectedException;
|
||||||
import org.springframework.beans.BeansException;
|
import org.springframework.beans.BeansException;
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.beans.NotWritablePropertyException;
|
import org.springframework.beans.NotWritablePropertyException;
|
||||||
|
|
@ -93,6 +102,7 @@ import org.springframework.tests.sample.beans.SideEffectBean;
|
||||||
import org.springframework.tests.sample.beans.TestBean;
|
import org.springframework.tests.sample.beans.TestBean;
|
||||||
import org.springframework.tests.sample.beans.factory.DummyFactory;
|
import org.springframework.tests.sample.beans.factory.DummyFactory;
|
||||||
import org.springframework.util.StopWatch;
|
import org.springframework.util.StopWatch;
|
||||||
|
import org.springframework.util.StringValueResolver;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests properties population and autowire behavior.
|
* Tests properties population and autowire behavior.
|
||||||
|
|
@ -102,11 +112,14 @@ import org.springframework.util.StopWatch;
|
||||||
* @author Rick Evans
|
* @author Rick Evans
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
public class DefaultListableBeanFactoryTests {
|
public class DefaultListableBeanFactoryTests {
|
||||||
|
|
||||||
private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class);
|
private static final Log factoryLog = LogFactory.getLog(DefaultListableBeanFactory.class);
|
||||||
|
|
||||||
|
@Rule
|
||||||
|
public ExpectedException thrown = ExpectedException.none();
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnreferencedSingletonWasInstantiated() {
|
public void testUnreferencedSingletonWasInstantiated() {
|
||||||
|
|
@ -1270,6 +1283,12 @@ public class DefaultListableBeanFactoryTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected=NoSuchBeanDefinitionException.class)
|
@Test(expected=NoSuchBeanDefinitionException.class)
|
||||||
|
public void testGetBeanByTypeWithNoneFound() {
|
||||||
|
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||||
|
lbf.getBean(TestBean.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=NoUniqueBeanDefinitionException.class)
|
||||||
public void testGetBeanByTypeWithAmbiguity() {
|
public void testGetBeanByTypeWithAmbiguity() {
|
||||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||||
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||||
|
|
@ -1279,6 +1298,32 @@ public class DefaultListableBeanFactoryTests {
|
||||||
lbf.getBean(TestBean.class);
|
lbf.getBean(TestBean.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetBeanByTypeWithPrimary() throws Exception {
|
||||||
|
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||||
|
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||||
|
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||||
|
bd2.setPrimary(true);
|
||||||
|
lbf.registerBeanDefinition("bd1", bd1);
|
||||||
|
lbf.registerBeanDefinition("bd2", bd2);
|
||||||
|
TestBean bean = lbf.getBean(TestBean.class);
|
||||||
|
assertThat(bean.getBeanName(), equalTo("bd2"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testGetBeanByTypeWithMultiplePrimary() throws Exception {
|
||||||
|
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||||
|
RootBeanDefinition bd1 = new RootBeanDefinition(TestBean.class);
|
||||||
|
bd1.setPrimary(true);
|
||||||
|
RootBeanDefinition bd2 = new RootBeanDefinition(TestBean.class);
|
||||||
|
bd2.setPrimary(true);
|
||||||
|
lbf.registerBeanDefinition("bd1", bd1);
|
||||||
|
lbf.registerBeanDefinition("bd2", bd2);
|
||||||
|
thrown.expect(NoUniqueBeanDefinitionException.class);
|
||||||
|
thrown.expectMessage(containsString("more than one 'primary'"));
|
||||||
|
lbf.getBean(TestBean.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testGetBeanByTypeFiltersOutNonAutowireCandidates() {
|
public void testGetBeanByTypeFiltersOutNonAutowireCandidates() {
|
||||||
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
DefaultListableBeanFactory lbf = new DefaultListableBeanFactory();
|
||||||
|
|
@ -1296,7 +1341,8 @@ public class DefaultListableBeanFactoryTests {
|
||||||
try {
|
try {
|
||||||
lbf.getBean(TestBean.class);
|
lbf.getBean(TestBean.class);
|
||||||
fail("Should have thrown NoSuchBeanDefinitionException");
|
fail("Should have thrown NoSuchBeanDefinitionException");
|
||||||
} catch (NoSuchBeanDefinitionException ex) {
|
}
|
||||||
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
// expected
|
// expected
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -2221,6 +2267,26 @@ public class DefaultListableBeanFactoryTests {
|
||||||
assertThat(bf.containsBean("bogus"), is(false));
|
assertThat(bf.containsBean("bogus"), is(false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void resolveEmbeddedValue() throws Exception {
|
||||||
|
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||||
|
StringValueResolver r1 = mock(StringValueResolver.class);
|
||||||
|
StringValueResolver r2 = mock(StringValueResolver.class);
|
||||||
|
StringValueResolver r3 = mock(StringValueResolver.class);
|
||||||
|
bf.addEmbeddedValueResolver(r1);
|
||||||
|
bf.addEmbeddedValueResolver(r2);
|
||||||
|
bf.addEmbeddedValueResolver(r3);
|
||||||
|
given(r1.resolveStringValue("A")).willReturn("B");
|
||||||
|
given(r2.resolveStringValue("B")).willReturn(null);
|
||||||
|
given(r3.resolveStringValue(isNull(String.class))).willThrow(new IllegalArgumentException());
|
||||||
|
|
||||||
|
bf.resolveEmbeddedValue("A");
|
||||||
|
|
||||||
|
verify(r1).resolveStringValue("A");
|
||||||
|
verify(r2).resolveStringValue("B");
|
||||||
|
verify(r3, never()).resolveStringValue(isNull(String.class));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static class A { }
|
static class A { }
|
||||||
static class B { }
|
static class B { }
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -18,9 +18,12 @@ package org.springframework.cache.ehcache;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
import net.sf.ehcache.CacheException;
|
import net.sf.ehcache.CacheException;
|
||||||
import net.sf.ehcache.CacheManager;
|
import net.sf.ehcache.CacheManager;
|
||||||
|
import net.sf.ehcache.config.Configuration;
|
||||||
|
import net.sf.ehcache.config.ConfigurationFactory;
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
|
@ -28,6 +31,8 @@ import org.springframework.beans.factory.DisposableBean;
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link FactoryBean} that exposes an EHCache {@link net.sf.ehcache.CacheManager}
|
* {@link FactoryBean} that exposes an EHCache {@link net.sf.ehcache.CacheManager}
|
||||||
|
|
@ -54,6 +59,10 @@ import org.springframework.core.io.Resource;
|
||||||
*/
|
*/
|
||||||
public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean, DisposableBean {
|
public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean, DisposableBean {
|
||||||
|
|
||||||
|
// Check whether EHCache 2.1+ CacheManager.create(Configuration) method is available...
|
||||||
|
private static final Method createWithConfiguration =
|
||||||
|
ClassUtils.getMethodIfAvailable(CacheManager.class, "create", Configuration.class);
|
||||||
|
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
private Resource configLocation;
|
private Resource configLocation;
|
||||||
|
|
@ -98,21 +107,42 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
|
||||||
|
|
||||||
public void afterPropertiesSet() throws IOException, CacheException {
|
public void afterPropertiesSet() throws IOException, CacheException {
|
||||||
logger.info("Initializing EHCache CacheManager");
|
logger.info("Initializing EHCache CacheManager");
|
||||||
if (this.configLocation != null) {
|
InputStream is = (this.configLocation != null ? this.configLocation.getInputStream() : null);
|
||||||
InputStream is = this.configLocation.getInputStream();
|
try {
|
||||||
try {
|
// A bit convoluted for EHCache 1.x/2.0 compatibility.
|
||||||
this.cacheManager = (this.shared ? CacheManager.create(is) : new CacheManager(is));
|
// To be much simpler once we require EHCache 2.1+
|
||||||
|
if (this.cacheManagerName != null) {
|
||||||
|
if (this.shared && createWithConfiguration == null) {
|
||||||
|
// No CacheManager.create(Configuration) method available before EHCache 2.1;
|
||||||
|
// can only set CacheManager name after creation.
|
||||||
|
this.cacheManager = (is != null ? CacheManager.create(is) : CacheManager.create());
|
||||||
|
this.cacheManager.setName(this.cacheManagerName);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Configuration configuration = (is != null ? ConfigurationFactory.parseConfiguration(is) :
|
||||||
|
ConfigurationFactory.parseConfiguration());
|
||||||
|
configuration.setName(this.cacheManagerName);
|
||||||
|
if (this.shared) {
|
||||||
|
this.cacheManager = (CacheManager) ReflectionUtils.invokeMethod(createWithConfiguration, null, configuration);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.cacheManager = new CacheManager(configuration);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally {
|
// For strict backwards compatibility: use simplest possible constructors...
|
||||||
|
else if (this.shared) {
|
||||||
|
this.cacheManager = (is != null ? CacheManager.create(is) : CacheManager.create());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.cacheManager = (is != null ? new CacheManager(is) : new CacheManager());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (is != null) {
|
||||||
is.close();
|
is.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
this.cacheManager = (this.shared ? CacheManager.create() : new CacheManager());
|
|
||||||
}
|
|
||||||
if (this.cacheManagerName != null) {
|
|
||||||
this.cacheManager.setName(this.cacheManagerName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -35,6 +35,7 @@ import javax.mail.internet.MimeBodyPart;
|
||||||
import javax.mail.internet.MimeMessage;
|
import javax.mail.internet.MimeMessage;
|
||||||
import javax.mail.internet.MimeMultipart;
|
import javax.mail.internet.MimeMultipart;
|
||||||
import javax.mail.internet.MimePart;
|
import javax.mail.internet.MimePart;
|
||||||
|
import javax.mail.internet.MimeUtility;
|
||||||
|
|
||||||
import org.springframework.core.io.InputStreamSource;
|
import org.springframework.core.io.InputStreamSource;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
|
|
@ -960,7 +961,7 @@ public class MimeMessageHelper {
|
||||||
* @see #addInline(String, javax.activation.DataSource)
|
* @see #addInline(String, javax.activation.DataSource)
|
||||||
*/
|
*/
|
||||||
public void addInline(String contentId, InputStreamSource inputStreamSource, String contentType)
|
public void addInline(String contentId, InputStreamSource inputStreamSource, String contentType)
|
||||||
throws MessagingException {
|
throws MessagingException {
|
||||||
|
|
||||||
Assert.notNull(inputStreamSource, "InputStreamSource must not be null");
|
Assert.notNull(inputStreamSource, "InputStreamSource must not be null");
|
||||||
if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
|
if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
|
||||||
|
|
@ -989,11 +990,16 @@ public class MimeMessageHelper {
|
||||||
public void addAttachment(String attachmentFilename, DataSource dataSource) throws MessagingException {
|
public void addAttachment(String attachmentFilename, DataSource dataSource) throws MessagingException {
|
||||||
Assert.notNull(attachmentFilename, "Attachment filename must not be null");
|
Assert.notNull(attachmentFilename, "Attachment filename must not be null");
|
||||||
Assert.notNull(dataSource, "DataSource must not be null");
|
Assert.notNull(dataSource, "DataSource must not be null");
|
||||||
MimeBodyPart mimeBodyPart = new MimeBodyPart();
|
try {
|
||||||
mimeBodyPart.setDisposition(MimeBodyPart.ATTACHMENT);
|
MimeBodyPart mimeBodyPart = new MimeBodyPart();
|
||||||
mimeBodyPart.setFileName(attachmentFilename);
|
mimeBodyPart.setDisposition(MimeBodyPart.ATTACHMENT);
|
||||||
mimeBodyPart.setDataHandler(new DataHandler(dataSource));
|
mimeBodyPart.setFileName(MimeUtility.encodeText(attachmentFilename));
|
||||||
getRootMimeMultipart().addBodyPart(mimeBodyPart);
|
mimeBodyPart.setDataHandler(new DataHandler(dataSource));
|
||||||
|
getRootMimeMultipart().addBodyPart(mimeBodyPart);
|
||||||
|
}
|
||||||
|
catch (UnsupportedEncodingException ex) {
|
||||||
|
throw new MessagingException("Failed to encode attachment filename", ex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -1035,7 +1041,7 @@ public class MimeMessageHelper {
|
||||||
* @see org.springframework.core.io.Resource
|
* @see org.springframework.core.io.Resource
|
||||||
*/
|
*/
|
||||||
public void addAttachment(String attachmentFilename, InputStreamSource inputStreamSource)
|
public void addAttachment(String attachmentFilename, InputStreamSource inputStreamSource)
|
||||||
throws MessagingException {
|
throws MessagingException {
|
||||||
|
|
||||||
String contentType = getFileTypeMap().getContentType(attachmentFilename);
|
String contentType = getFileTypeMap().getContentType(attachmentFilename);
|
||||||
addAttachment(attachmentFilename, inputStreamSource, contentType);
|
addAttachment(attachmentFilename, inputStreamSource, contentType);
|
||||||
|
|
@ -1059,7 +1065,7 @@ public class MimeMessageHelper {
|
||||||
*/
|
*/
|
||||||
public void addAttachment(
|
public void addAttachment(
|
||||||
String attachmentFilename, InputStreamSource inputStreamSource, String contentType)
|
String attachmentFilename, InputStreamSource inputStreamSource, String contentType)
|
||||||
throws MessagingException {
|
throws MessagingException {
|
||||||
|
|
||||||
Assert.notNull(inputStreamSource, "InputStreamSource must not be null");
|
Assert.notNull(inputStreamSource, "InputStreamSource must not be null");
|
||||||
if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
|
if (inputStreamSource instanceof Resource && ((Resource) inputStreamSource).isOpen()) {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -20,6 +20,7 @@ import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
@ -147,7 +148,7 @@ public class FreeMarkerConfigurationFactory {
|
||||||
* @see #setPostTemplateLoaders
|
* @see #setPostTemplateLoaders
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public void setTemplateLoaders(TemplateLoader[] templateLoaders) {
|
public void setTemplateLoaders(TemplateLoader... templateLoaders) {
|
||||||
if (templateLoaders != null) {
|
if (templateLoaders != null) {
|
||||||
this.templateLoaders.addAll(Arrays.asList(templateLoaders));
|
this.templateLoaders.addAll(Arrays.asList(templateLoaders));
|
||||||
}
|
}
|
||||||
|
|
@ -164,7 +165,7 @@ public class FreeMarkerConfigurationFactory {
|
||||||
* @see #setTemplateLoaderPaths
|
* @see #setTemplateLoaderPaths
|
||||||
* @see #postProcessTemplateLoaders
|
* @see #postProcessTemplateLoaders
|
||||||
*/
|
*/
|
||||||
public void setPreTemplateLoaders(TemplateLoader[] preTemplateLoaders) {
|
public void setPreTemplateLoaders(TemplateLoader... preTemplateLoaders) {
|
||||||
this.preTemplateLoaders = Arrays.asList(preTemplateLoaders);
|
this.preTemplateLoaders = Arrays.asList(preTemplateLoaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,7 +180,7 @@ public class FreeMarkerConfigurationFactory {
|
||||||
* @see #setTemplateLoaderPaths
|
* @see #setTemplateLoaderPaths
|
||||||
* @see #postProcessTemplateLoaders
|
* @see #postProcessTemplateLoaders
|
||||||
*/
|
*/
|
||||||
public void setPostTemplateLoaders(TemplateLoader[] postTemplateLoaders) {
|
public void setPostTemplateLoaders(TemplateLoader... postTemplateLoaders) {
|
||||||
this.postTemplateLoaders = Arrays.asList(postTemplateLoaders);
|
this.postTemplateLoaders = Arrays.asList(postTemplateLoaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -211,7 +212,7 @@ public class FreeMarkerConfigurationFactory {
|
||||||
* @see SpringTemplateLoader
|
* @see SpringTemplateLoader
|
||||||
* @see #setTemplateLoaders
|
* @see #setTemplateLoaders
|
||||||
*/
|
*/
|
||||||
public void setTemplateLoaderPaths(String[] templateLoaderPaths) {
|
public void setTemplateLoaderPaths(String... templateLoaderPaths) {
|
||||||
this.templateLoaderPaths = templateLoaderPaths;
|
this.templateLoaderPaths = templateLoaderPaths;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -229,7 +230,7 @@ public class FreeMarkerConfigurationFactory {
|
||||||
* Return the Spring ResourceLoader to use for loading FreeMarker template files.
|
* Return the Spring ResourceLoader to use for loading FreeMarker template files.
|
||||||
*/
|
*/
|
||||||
protected ResourceLoader getResourceLoader() {
|
protected ResourceLoader getResourceLoader() {
|
||||||
return resourceLoader;
|
return this.resourceLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -252,7 +253,7 @@ public class FreeMarkerConfigurationFactory {
|
||||||
* Return whether to prefer file system access for template loading.
|
* Return whether to prefer file system access for template loading.
|
||||||
*/
|
*/
|
||||||
protected boolean isPreferFileSystemAccess() {
|
protected boolean isPreferFileSystemAccess() {
|
||||||
return preferFileSystemAccess;
|
return this.preferFileSystemAccess;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -293,25 +294,27 @@ public class FreeMarkerConfigurationFactory {
|
||||||
config.setDefaultEncoding(this.defaultEncoding);
|
config.setDefaultEncoding(this.defaultEncoding);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
List<TemplateLoader> templateLoaders = new LinkedList<TemplateLoader>(this.templateLoaders);
|
||||||
|
|
||||||
// Register template loaders that are supposed to kick in early.
|
// Register template loaders that are supposed to kick in early.
|
||||||
if (this.preTemplateLoaders != null) {
|
if (this.preTemplateLoaders != null) {
|
||||||
this.templateLoaders.addAll(this.preTemplateLoaders);
|
templateLoaders.addAll(this.preTemplateLoaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register default template loaders.
|
// Register default template loaders.
|
||||||
if (this.templateLoaderPaths != null) {
|
if (this.templateLoaderPaths != null) {
|
||||||
for (String path : this.templateLoaderPaths) {
|
for (String path : this.templateLoaderPaths) {
|
||||||
this.templateLoaders.add(getTemplateLoaderForPath(path));
|
templateLoaders.add(getTemplateLoaderForPath(path));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
postProcessTemplateLoaders(this.templateLoaders);
|
postProcessTemplateLoaders(templateLoaders);
|
||||||
|
|
||||||
// Register template loaders that are supposed to kick in late.
|
// Register template loaders that are supposed to kick in late.
|
||||||
if (this.postTemplateLoaders != null) {
|
if (this.postTemplateLoaders != null) {
|
||||||
this.templateLoaders.addAll(this.postTemplateLoaders);
|
templateLoaders.addAll(this.postTemplateLoaders);
|
||||||
}
|
}
|
||||||
|
|
||||||
TemplateLoader loader = getAggregateTemplateLoader(this.templateLoaders);
|
TemplateLoader loader = getAggregateTemplateLoader(templateLoaders);
|
||||||
if (loader != null) {
|
if (loader != null) {
|
||||||
config.setTemplateLoader(loader);
|
config.setTemplateLoader(loader);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -38,6 +38,7 @@ public class EhCacheSupportTests extends TestCase {
|
||||||
|
|
||||||
public void testLoadingBlankCacheManager() throws Exception {
|
public void testLoadingBlankCacheManager() throws Exception {
|
||||||
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
|
EhCacheManagerFactoryBean cacheManagerFb = new EhCacheManagerFactoryBean();
|
||||||
|
cacheManagerFb.setCacheManagerName("myCacheManager");
|
||||||
assertEquals(CacheManager.class, cacheManagerFb.getObjectType());
|
assertEquals(CacheManager.class, cacheManagerFb.getObjectType());
|
||||||
assertTrue("Singleton property", cacheManagerFb.isSingleton());
|
assertTrue("Singleton property", cacheManagerFb.isSingleton());
|
||||||
cacheManagerFb.afterPropertiesSet();
|
cacheManagerFb.afterPropertiesSet();
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -26,7 +26,6 @@ import java.util.concurrent.ConcurrentMap;
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.cache.Cache;
|
import org.springframework.cache.Cache;
|
||||||
import org.springframework.cache.CacheManager;
|
import org.springframework.cache.CacheManager;
|
||||||
import org.springframework.util.Assert;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class implementing the common {@link CacheManager} methods.
|
* Abstract base class implementing the common {@link CacheManager} methods.
|
||||||
|
|
@ -45,10 +44,10 @@ public abstract class AbstractCacheManager implements CacheManager, Initializing
|
||||||
|
|
||||||
public void afterPropertiesSet() {
|
public void afterPropertiesSet() {
|
||||||
Collection<? extends Cache> caches = loadCaches();
|
Collection<? extends Cache> caches = loadCaches();
|
||||||
Assert.notEmpty(caches, "loadCaches must not return an empty Collection");
|
|
||||||
this.cacheMap.clear();
|
|
||||||
|
|
||||||
// preserve the initial order of the cache names
|
// preserve the initial order of the cache names
|
||||||
|
this.cacheMap.clear();
|
||||||
|
this.cacheNames.clear();
|
||||||
for (Cache cache : caches) {
|
for (Cache cache : caches) {
|
||||||
this.cacheMap.put(cache.getName(), decorateCache(cache));
|
this.cacheMap.put(cache.getName(), decorateCache(cache));
|
||||||
this.cacheNames.add(cache.getName());
|
this.cacheNames.add(cache.getName());
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -39,9 +39,10 @@ import static org.springframework.context.annotation.MetadataUtils.*;
|
||||||
*/
|
*/
|
||||||
public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
|
public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
|
||||||
|
|
||||||
|
private final ScopedProxyMode defaultProxyMode;
|
||||||
|
|
||||||
protected Class<? extends Annotation> scopeAnnotationType = Scope.class;
|
protected Class<? extends Annotation> scopeAnnotationType = Scope.class;
|
||||||
|
|
||||||
private final ScopedProxyMode defaultProxyMode;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the {@code AnnotationScopeMetadataResolver} class.
|
* Create a new instance of the {@code AnnotationScopeMetadataResolver} class.
|
||||||
|
|
@ -77,8 +78,7 @@ public class AnnotationScopeMetadataResolver implements ScopeMetadataResolver {
|
||||||
ScopeMetadata metadata = new ScopeMetadata();
|
ScopeMetadata metadata = new ScopeMetadata();
|
||||||
if (definition instanceof AnnotatedBeanDefinition) {
|
if (definition instanceof AnnotatedBeanDefinition) {
|
||||||
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
|
||||||
AnnotationAttributes attributes =
|
AnnotationAttributes attributes = attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
|
||||||
attributesFor(annDef.getMetadata(), this.scopeAnnotationType);
|
|
||||||
if (attributes != null) {
|
if (attributes != null) {
|
||||||
metadata.setScopeName(attributes.getString("value"));
|
metadata.setScopeName(attributes.getString("value"));
|
||||||
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
|
ScopedProxyMode proxyMode = attributes.getEnum("proxyMode");
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,7 +17,6 @@
|
||||||
package org.springframework.context.support;
|
package org.springframework.context.support;
|
||||||
|
|
||||||
import org.springframework.beans.factory.BeanNameAware;
|
import org.springframework.beans.factory.BeanNameAware;
|
||||||
|
|
||||||
import org.springframework.beans.factory.InitializingBean;
|
import org.springframework.beans.factory.InitializingBean;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
@ -114,12 +113,13 @@ public abstract class AbstractRefreshableConfigApplicationContext extends Abstra
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve the given path, replacing placeholders with corresponding
|
* Resolve the given path, replacing placeholders with corresponding
|
||||||
* system property values if necessary. Applied to config locations.
|
* environment property values if necessary. Applied to config locations.
|
||||||
* @param path the original file path
|
* @param path the original file path
|
||||||
* @return the resolved file path
|
* @return the resolved file path
|
||||||
|
* @see org.springframework.core.env.Environment#resolveRequiredPlaceholders(String)
|
||||||
*/
|
*/
|
||||||
protected String resolvePath(String path) {
|
protected String resolvePath(String path) {
|
||||||
return this.getEnvironment().resolveRequiredPlaceholders(path);
|
return getEnvironment().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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -70,9 +70,9 @@ public class MessageSourceResourceBundle extends ResourceBundle {
|
||||||
* Returns {@code null} if the message could not be resolved.
|
* Returns {@code null} if the message could not be resolved.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
protected Object handleGetObject(String code) {
|
protected Object handleGetObject(String key) {
|
||||||
try {
|
try {
|
||||||
return this.messageSource.getMessage(code, null, this.locale);
|
return this.messageSource.getMessage(key, null, this.locale);
|
||||||
}
|
}
|
||||||
catch (NoSuchMessageException ex) {
|
catch (NoSuchMessageException ex) {
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -80,12 +80,29 @@ public class MessageSourceResourceBundle extends ResourceBundle {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implementation returns {@code null}, as a MessageSource does
|
* This implementation checks whether the target MessageSource can resolve
|
||||||
* not allow for enumerating the defined message codes.
|
* a message for the given key, translating {@code NoSuchMessageException}
|
||||||
|
* accordingly. In contrast to ResourceBundle's default implementation in
|
||||||
|
* JDK 1.6, this does not rely on the capability to enumerate message keys.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean containsKey(String key) {
|
||||||
|
try {
|
||||||
|
this.messageSource.getMessage(key, null, this.locale);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
catch (NoSuchMessageException ex) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This implementation throws {@code UnsupportedOperationException},
|
||||||
|
* as a MessageSource does not allow for enumerating the defined message codes.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Enumeration<String> getKeys() {
|
public Enumeration<String> getKeys() {
|
||||||
return null;
|
throw new UnsupportedOperationException("MessageSourceResourceBundle does not support enumerating its keys");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -71,8 +71,6 @@ import org.springframework.context.access.ContextSingletonBeanFactoryLocator;
|
||||||
* @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
|
* @see org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor
|
||||||
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
|
* @see org.springframework.context.access.ContextSingletonBeanFactoryLocator
|
||||||
* @see #getBeanFactoryLocatorKey
|
* @see #getBeanFactoryLocatorKey
|
||||||
* @see org.springframework.ejb.support.AbstractEnterpriseBean#setBeanFactoryLocator
|
|
||||||
* @see org.springframework.ejb.support.AbstractEnterpriseBean#setBeanFactoryLocatorKey
|
|
||||||
*/
|
*/
|
||||||
public class SpringBeanAutowiringInterceptor {
|
public class SpringBeanAutowiringInterceptor {
|
||||||
|
|
||||||
|
|
@ -99,9 +97,15 @@ public class SpringBeanAutowiringInterceptor {
|
||||||
invocationContext.proceed();
|
invocationContext.proceed();
|
||||||
}
|
}
|
||||||
catch (RuntimeException ex) {
|
catch (RuntimeException ex) {
|
||||||
|
doReleaseBean(invocationContext.getTarget());
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
|
catch (Error err) {
|
||||||
|
doReleaseBean(invocationContext.getTarget());
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
|
doReleaseBean(invocationContext.getTarget());
|
||||||
// Cannot declare a checked exception on WebSphere here - so we need to wrap.
|
// Cannot declare a checked exception on WebSphere here - so we need to wrap.
|
||||||
throw new EJBException(ex);
|
throw new EJBException(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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -57,7 +57,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||||
* @param dateFormatter the date formatter
|
* @param dateFormatter the date formatter
|
||||||
*/
|
*/
|
||||||
public void setFormatter(DateFormatter dateFormatter) {
|
public void setFormatter(DateFormatter dateFormatter) {
|
||||||
Assert.notNull(dateFormatter,"DateFormatter must not be null");
|
Assert.notNull(dateFormatter, "DateFormatter must not be null");
|
||||||
this.dateFormatter = dateFormatter;
|
this.dateFormatter = dateFormatter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -35,6 +35,7 @@ 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 Keith Donald
|
||||||
|
* @author Phillip Webb
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
final class JodaTimeConverters {
|
final class JodaTimeConverters {
|
||||||
|
|
@ -55,6 +56,7 @@ final class JodaTimeConverters {
|
||||||
registry.addConverter(new DateTimeToCalendarConverter());
|
registry.addConverter(new DateTimeToCalendarConverter());
|
||||||
registry.addConverter(new DateTimeToLongConverter());
|
registry.addConverter(new DateTimeToLongConverter());
|
||||||
registry.addConverter(new CalendarToReadableInstantConverter());
|
registry.addConverter(new CalendarToReadableInstantConverter());
|
||||||
|
registry.addConverter(new DateToReadableInstantConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -159,4 +161,14 @@ final class JodaTimeConverters {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Used when printing a java.util.Date field with a ReadableInstantPrinter.
|
||||||
|
* @see MillisecondInstantPrinter
|
||||||
|
* @see JodaDateTimeFormatAnnotationFormatterFactory
|
||||||
|
*/
|
||||||
|
private static class DateToReadableInstantConverter implements Converter<Date, ReadableInstant> {
|
||||||
|
public ReadableInstant convert(Date source) {
|
||||||
|
return new DateTime(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -30,6 +30,8 @@ import javax.management.modelmbean.ModelMBeanOperationInfo;
|
||||||
import org.springframework.aop.framework.AopProxyUtils;
|
import org.springframework.aop.framework.AopProxyUtils;
|
||||||
import org.springframework.aop.support.AopUtils;
|
import org.springframework.aop.support.AopUtils;
|
||||||
import org.springframework.beans.BeanUtils;
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.core.LocalVariableTableParameterNameDiscoverer;
|
||||||
|
import org.springframework.core.ParameterNameDiscoverer;
|
||||||
import org.springframework.jmx.support.JmxUtils;
|
import org.springframework.jmx.support.JmxUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -49,6 +51,7 @@ import org.springframework.jmx.support.JmxUtils;
|
||||||
*
|
*
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author David Boden
|
||||||
* @since 1.2
|
* @since 1.2
|
||||||
* @see #includeOperation
|
* @see #includeOperation
|
||||||
* @see #includeReadAttribute
|
* @see #includeReadAttribute
|
||||||
|
|
@ -177,6 +180,8 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
||||||
|
|
||||||
private boolean exposeClassDescriptor = false;
|
private boolean exposeClassDescriptor = false;
|
||||||
|
|
||||||
|
private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the default for the JMX field "currencyTimeLimit".
|
* Set the default for the JMX field "currencyTimeLimit".
|
||||||
|
|
@ -254,6 +259,23 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
||||||
return this.exposeClassDescriptor;
|
return this.exposeClassDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the ParameterNameDiscoverer to use for resolving method parameter
|
||||||
|
* names if needed (e.g. for parameter names of MBean operation methods).
|
||||||
|
* <p>The default is {@link LocalVariableTableParameterNameDiscoverer}.
|
||||||
|
*/
|
||||||
|
public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
|
||||||
|
this.parameterNameDiscoverer = parameterNameDiscoverer;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the ParameterNameDiscoverer to use for resolving method parameter
|
||||||
|
* names if needed (may be {@code null} in order to skip parameter detection).
|
||||||
|
*/
|
||||||
|
protected ParameterNameDiscoverer getParameterNameDiscoverer() {
|
||||||
|
return this.parameterNameDiscoverer;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Iterate through all properties on the MBean class and gives subclasses
|
* Iterate through all properties on the MBean class and gives subclasses
|
||||||
|
|
@ -381,7 +403,8 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
||||||
* Creates an instance of {@code ModelMBeanOperationInfo} for the
|
* Creates an instance of {@code ModelMBeanOperationInfo} for the
|
||||||
* given method. Populates the parameter info for the operation.
|
* given method. Populates the parameter info for the operation.
|
||||||
* @param method the {@code Method} to create a {@code ModelMBeanOperationInfo} for
|
* @param method the {@code Method} to create a {@code ModelMBeanOperationInfo} for
|
||||||
* @param name the name for the operation info
|
* @param name the logical name for the operation (method name or property name);
|
||||||
|
* not used by the default implementation but possibly by subclasses
|
||||||
* @param beanKey the key associated with the MBean in the beans map
|
* @param beanKey the key associated with the MBean in the beans map
|
||||||
* of the {@code MBeanExporter}
|
* of the {@code MBeanExporter}
|
||||||
* @return the {@code ModelMBeanOperationInfo}
|
* @return the {@code ModelMBeanOperationInfo}
|
||||||
|
|
@ -392,7 +415,7 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
||||||
return new ModelMBeanOperationInfo(getOperationDescription(method, beanKey), method);
|
return new ModelMBeanOperationInfo(getOperationDescription(method, beanKey), method);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new ModelMBeanOperationInfo(name,
|
return new ModelMBeanOperationInfo(method.getName(),
|
||||||
getOperationDescription(method, beanKey),
|
getOperationDescription(method, beanKey),
|
||||||
getOperationParameters(method, beanKey),
|
getOperationParameters(method, beanKey),
|
||||||
method.getReturnType().getName(),
|
method.getReturnType().getName(),
|
||||||
|
|
@ -476,16 +499,27 @@ public abstract class AbstractReflectiveMBeanInfoAssembler extends AbstractMBean
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create parameter info for the given method.
|
* Create parameter info for the given method.
|
||||||
* <p>The default implementation returns an empty arry of {@code MBeanParameterInfo}.
|
* <p>The default implementation returns an empty array of {@code MBeanParameterInfo}.
|
||||||
* @param method the {@code Method} to get the parameter information for
|
* @param method the {@code Method} to get the parameter information for
|
||||||
* @param beanKey the key associated with the MBean in the beans map
|
* @param beanKey the key associated with the MBean in the beans map
|
||||||
* of the {@code MBeanExporter}
|
* of the {@code MBeanExporter}
|
||||||
* @return the {@code MBeanParameterInfo} array
|
* @return the {@code MBeanParameterInfo} array
|
||||||
*/
|
*/
|
||||||
protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) {
|
protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) {
|
||||||
return new MBeanParameterInfo[0];
|
ParameterNameDiscoverer paramNameDiscoverer = getParameterNameDiscoverer();
|
||||||
}
|
String[] paramNames = (paramNameDiscoverer != null ? paramNameDiscoverer.getParameterNames(method) : null);
|
||||||
|
if (paramNames == null) {
|
||||||
|
return new MBeanParameterInfo[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
MBeanParameterInfo[] info = new MBeanParameterInfo[paramNames.length];
|
||||||
|
Class<?>[] typeParameters = method.getParameterTypes();
|
||||||
|
for(int i = 0; i < info.length; i++) {
|
||||||
|
info[i] = new MBeanParameterInfo(paramNames[i], typeParameters[i].getName(), paramNames[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return info;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allows subclasses to add extra fields to the {@code Descriptor} for an MBean.
|
* Allows subclasses to add extra fields to the {@code Descriptor} for an MBean.
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -36,6 +36,7 @@ import org.springframework.jmx.export.metadata.ManagedOperationParameter;
|
||||||
import org.springframework.jmx.export.metadata.ManagedResource;
|
import org.springframework.jmx.export.metadata.ManagedResource;
|
||||||
import org.springframework.jmx.support.MetricType;
|
import org.springframework.jmx.support.MetricType;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -255,19 +256,17 @@ public class MetadataMBeanInfoAssembler extends AbstractReflectiveMBeanInfoAssem
|
||||||
@Override
|
@Override
|
||||||
protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) {
|
protected MBeanParameterInfo[] getOperationParameters(Method method, String beanKey) {
|
||||||
ManagedOperationParameter[] params = this.attributeSource.getManagedOperationParameters(method);
|
ManagedOperationParameter[] params = this.attributeSource.getManagedOperationParameters(method);
|
||||||
if (params == null || params.length == 0) {
|
if (ObjectUtils.isEmpty(params)) {
|
||||||
return new MBeanParameterInfo[0];
|
return super.getOperationParameters(method, beanKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
MBeanParameterInfo[] parameterInfo = new MBeanParameterInfo[params.length];
|
MBeanParameterInfo[] parameterInfo = new MBeanParameterInfo[params.length];
|
||||||
Class[] methodParameters = method.getParameterTypes();
|
Class[] methodParameters = method.getParameterTypes();
|
||||||
|
|
||||||
for (int i = 0; i < params.length; i++) {
|
for (int i = 0; i < params.length; i++) {
|
||||||
ManagedOperationParameter param = params[i];
|
ManagedOperationParameter param = params[i];
|
||||||
parameterInfo[i] =
|
parameterInfo[i] =
|
||||||
new MBeanParameterInfo(param.getName(), methodParameters[i].getName(), param.getDescription());
|
new MBeanParameterInfo(param.getName(), methodParameters[i].getName(), param.getDescription());
|
||||||
}
|
}
|
||||||
|
|
||||||
return parameterInfo;
|
return parameterInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.springframework.jmx.support;
|
package org.springframework.jmx.support;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import javax.management.InstanceAlreadyExistsException;
|
import javax.management.InstanceAlreadyExistsException;
|
||||||
|
|
@ -112,7 +113,7 @@ public class MBeanRegistrationSupport {
|
||||||
/**
|
/**
|
||||||
* The beans that have been registered by this exporter.
|
* The beans that have been registered by this exporter.
|
||||||
*/
|
*/
|
||||||
protected final Set<ObjectName> registeredBeans = new LinkedHashSet<ObjectName>();
|
private final Set<ObjectName> registeredBeans = Collections.synchronizedSet(new LinkedHashSet<ObjectName>());
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The policy used when registering an MBean and finding that it already exists.
|
* The policy used when registering an MBean and finding that it already exists.
|
||||||
|
|
@ -228,10 +229,9 @@ public class MBeanRegistrationSupport {
|
||||||
* Unregisters all beans that have been registered by an instance of this class.
|
* Unregisters all beans that have been registered by an instance of this class.
|
||||||
*/
|
*/
|
||||||
protected void unregisterBeans() {
|
protected void unregisterBeans() {
|
||||||
for (ObjectName objectName : this.registeredBeans) {
|
for (ObjectName objectName : new LinkedHashSet<ObjectName>(this.registeredBeans)) {
|
||||||
doUnregister(objectName);
|
doUnregister(objectName);
|
||||||
}
|
}
|
||||||
this.registeredBeans.clear();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -257,6 +257,7 @@ public class MBeanRegistrationSupport {
|
||||||
logger.error("Could not unregister MBean [" + objectName + "]", ex);
|
logger.error("Could not unregister MBean [" + objectName + "]", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this.registeredBeans.remove(objectName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -19,7 +19,7 @@ package org.springframework.remoting.rmi;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.rmi.RemoteException;
|
import java.rmi.RemoteException;
|
||||||
|
import javax.naming.Context;
|
||||||
import javax.naming.NamingException;
|
import javax.naming.NamingException;
|
||||||
import javax.rmi.PortableRemoteObject;
|
import javax.rmi.PortableRemoteObject;
|
||||||
|
|
||||||
|
|
@ -88,6 +88,8 @@ public class JndiRmiClientInterceptor extends JndiObjectLocator implements Metho
|
||||||
|
|
||||||
private boolean refreshStubOnConnectFailure = false;
|
private boolean refreshStubOnConnectFailure = false;
|
||||||
|
|
||||||
|
private boolean exposeAccessContext = false;
|
||||||
|
|
||||||
private Object cachedStub;
|
private Object cachedStub;
|
||||||
|
|
||||||
private final Object stubMonitor = new Object();
|
private final Object stubMonitor = new Object();
|
||||||
|
|
@ -166,6 +168,18 @@ public class JndiRmiClientInterceptor extends JndiObjectLocator implements Metho
|
||||||
this.refreshStubOnConnectFailure = refreshStubOnConnectFailure;
|
this.refreshStubOnConnectFailure = refreshStubOnConnectFailure;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set whether to expose the JNDI environment context for all access to the target
|
||||||
|
* RMI stub, i.e. for all method invocations on the exposed object reference.
|
||||||
|
* <p>Default is "false", i.e. to only expose the JNDI context for object lookup.
|
||||||
|
* Switch this flag to "true" in order to expose the JNDI environment (including
|
||||||
|
* the authorization context) for each RMI invocation, as needed by WebLogic
|
||||||
|
* for RMI stubs with authorization requirements.
|
||||||
|
*/
|
||||||
|
public void setExposeAccessContext(boolean exposeAccessContext) {
|
||||||
|
this.exposeAccessContext = exposeAccessContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void afterPropertiesSet() throws NamingException {
|
public void afterPropertiesSet() throws NamingException {
|
||||||
|
|
@ -190,8 +204,8 @@ public class JndiRmiClientInterceptor extends JndiObjectLocator implements Metho
|
||||||
else if (getServiceInterface() != null) {
|
else if (getServiceInterface() != null) {
|
||||||
boolean isImpl = getServiceInterface().isInstance(remoteObj);
|
boolean isImpl = getServiceInterface().isInstance(remoteObj);
|
||||||
logger.debug("Using service interface [" + getServiceInterface().getName() +
|
logger.debug("Using service interface [" + getServiceInterface().getName() +
|
||||||
"] for JNDI RMI object [" + getJndiName() + "] - " +
|
"] for JNDI RMI object [" + getJndiName() + "] - " +
|
||||||
(!isImpl ? "not " : "") + "directly implemented");
|
(!isImpl ? "not " : "") + "directly implemented");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (this.cacheStub) {
|
if (this.cacheStub) {
|
||||||
|
|
@ -268,13 +282,15 @@ public class JndiRmiClientInterceptor extends JndiObjectLocator implements Metho
|
||||||
* @see java.rmi.NoSuchObjectException
|
* @see java.rmi.NoSuchObjectException
|
||||||
*/
|
*/
|
||||||
public Object invoke(MethodInvocation invocation) throws Throwable {
|
public Object invoke(MethodInvocation invocation) throws Throwable {
|
||||||
Object stub = null;
|
Object stub;
|
||||||
try {
|
try {
|
||||||
stub = getStub();
|
stub = getStub();
|
||||||
}
|
}
|
||||||
catch (NamingException ex) {
|
catch (NamingException ex) {
|
||||||
throw new RemoteLookupFailureException("JNDI lookup for RMI service [" + getJndiName() + "] failed", ex);
|
throw new RemoteLookupFailureException("JNDI lookup for RMI service [" + getJndiName() + "] failed", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Context ctx = (this.exposeAccessContext ? getJndiTemplate().getContext() : null);
|
||||||
try {
|
try {
|
||||||
return doInvoke(invocation, stub);
|
return doInvoke(invocation, stub);
|
||||||
}
|
}
|
||||||
|
|
@ -297,6 +313,9 @@ public class JndiRmiClientInterceptor extends JndiObjectLocator implements Metho
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
getJndiTemplate().releaseContext(ctx);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -354,7 +373,7 @@ public class JndiRmiClientInterceptor extends JndiObjectLocator implements Metho
|
||||||
* @see #invoke
|
* @see #invoke
|
||||||
*/
|
*/
|
||||||
protected Object refreshAndRetry(MethodInvocation invocation) throws Throwable {
|
protected Object refreshAndRetry(MethodInvocation invocation) throws Throwable {
|
||||||
Object freshStub = null;
|
Object freshStub;
|
||||||
synchronized (this.stubMonitor) {
|
synchronized (this.stubMonitor) {
|
||||||
this.cachedStub = null;
|
this.cachedStub = null;
|
||||||
freshStub = lookupStub();
|
freshStub = lookupStub();
|
||||||
|
|
@ -426,7 +445,7 @@ public class JndiRmiClientInterceptor extends JndiObjectLocator implements Metho
|
||||||
* @see org.springframework.remoting.support.RemoteInvocation
|
* @see org.springframework.remoting.support.RemoteInvocation
|
||||||
*/
|
*/
|
||||||
protected Object doInvoke(MethodInvocation methodInvocation, RmiInvocationHandler invocationHandler)
|
protected Object doInvoke(MethodInvocation methodInvocation, RmiInvocationHandler invocationHandler)
|
||||||
throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
throws RemoteException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
|
||||||
|
|
||||||
if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {
|
if (AopUtils.isToStringMethod(methodInvocation.getMethod())) {
|
||||||
return "RMI invoker proxy for service URL [" + getJndiName() + "]";
|
return "RMI invoker proxy for service URL [" + getJndiName() + "]";
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -20,6 +20,7 @@ import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.RejectedExecutionHandler;
|
import java.util.concurrent.RejectedExecutionHandler;
|
||||||
import java.util.concurrent.ThreadFactory;
|
import java.util.concurrent.ThreadFactory;
|
||||||
import java.util.concurrent.ThreadPoolExecutor;
|
import java.util.concurrent.ThreadPoolExecutor;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
@ -54,6 +55,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
|
||||||
|
|
||||||
private boolean waitForTasksToCompleteOnShutdown = false;
|
private boolean waitForTasksToCompleteOnShutdown = false;
|
||||||
|
|
||||||
|
private int awaitTerminationSeconds = 0;
|
||||||
|
|
||||||
private String beanName;
|
private String beanName;
|
||||||
|
|
||||||
private ExecutorService executor;
|
private ExecutorService executor;
|
||||||
|
|
@ -85,9 +88,17 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether to wait for scheduled tasks to complete on shutdown.
|
* Set whether to wait for scheduled tasks to complete on shutdown,
|
||||||
* <p>Default is "false". Switch this to "true" if you prefer
|
* not interrupting running tasks and executing all tasks in the queue.
|
||||||
* fully completed tasks at the expense of a longer shutdown phase.
|
* <p>Default is "false", shutting down immediately through interrupting
|
||||||
|
* ongoing tasks and clearing the queue. Switch this flag to "true" if you
|
||||||
|
* prefer fully completed tasks at the expense of a longer shutdown phase.
|
||||||
|
* <p>Note that Spring's container shutdown continues while ongoing tasks
|
||||||
|
* are being completed. If you want this executor to block and wait for the
|
||||||
|
* termination of tasks before the rest of the container continues to shut
|
||||||
|
* down - e.g. in order to keep up other resources that your tasks may need -,
|
||||||
|
* set the {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"}
|
||||||
|
* property instead of or in addition to this property.
|
||||||
* @see java.util.concurrent.ExecutorService#shutdown()
|
* @see java.util.concurrent.ExecutorService#shutdown()
|
||||||
* @see java.util.concurrent.ExecutorService#shutdownNow()
|
* @see java.util.concurrent.ExecutorService#shutdownNow()
|
||||||
*/
|
*/
|
||||||
|
|
@ -95,6 +106,33 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
|
||||||
this.waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
|
this.waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the maximum number of seconds that this executor is supposed to block
|
||||||
|
* on shutdown in order to wait for remaining tasks to complete their execution
|
||||||
|
* before the rest of the container continues to shut down. This is particularly
|
||||||
|
* useful if your remaining tasks are likely to need access to other resources
|
||||||
|
* that are also managed by the container.
|
||||||
|
* <p>By default, this executor won't wait for the termination of tasks at all.
|
||||||
|
* It will either shut down immediately, interrupting ongoing tasks and clearing
|
||||||
|
* the remaining task queue - or, if the
|
||||||
|
* {@link #setWaitForTasksToCompleteOnShutdown "waitForTasksToCompleteOnShutdown"}
|
||||||
|
* flag has been set to {@code true}, it will continue to fully execute all
|
||||||
|
* ongoing tasks as well as all remaining tasks in the queue, in parallel to
|
||||||
|
* the rest of the container shutting down.
|
||||||
|
* <p>In either case, if you specify an await-termination period using this property,
|
||||||
|
* this executor will wait for the given time (max) for the termination of tasks.
|
||||||
|
* As a rule of thumb, specify a significantly higher timeout here if you set
|
||||||
|
* "waitForTasksToCompleteOnShutdown" to {@code true} at the same time,
|
||||||
|
* since all remaining tasks in the queue will still get executed - in contrast
|
||||||
|
* to the default shutdown behavior where it's just about waiting for currently
|
||||||
|
* executing tasks that aren't reacting to thread interruption.
|
||||||
|
* @see java.util.concurrent.ExecutorService#shutdown()
|
||||||
|
* @see java.util.concurrent.ExecutorService#awaitTermination
|
||||||
|
*/
|
||||||
|
public void setAwaitTerminationSeconds(int awaitTerminationSeconds) {
|
||||||
|
this.awaitTerminationSeconds = awaitTerminationSeconds;
|
||||||
|
}
|
||||||
|
|
||||||
public void setBeanName(String name) {
|
public void setBeanName(String name) {
|
||||||
this.beanName = name;
|
this.beanName = name;
|
||||||
}
|
}
|
||||||
|
|
@ -145,6 +183,8 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
|
||||||
/**
|
/**
|
||||||
* Perform a shutdown on the ThreadPoolExecutor.
|
* Perform a shutdown on the ThreadPoolExecutor.
|
||||||
* @see java.util.concurrent.ExecutorService#shutdown()
|
* @see java.util.concurrent.ExecutorService#shutdown()
|
||||||
|
* @see java.util.concurrent.ExecutorService#shutdownNow()
|
||||||
|
* @see #awaitTerminationIfNecessary()
|
||||||
*/
|
*/
|
||||||
public void shutdown() {
|
public void shutdown() {
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
|
|
@ -156,6 +196,31 @@ public abstract class ExecutorConfigurationSupport extends CustomizableThreadFac
|
||||||
else {
|
else {
|
||||||
this.executor.shutdownNow();
|
this.executor.shutdownNow();
|
||||||
}
|
}
|
||||||
|
awaitTerminationIfNecessary();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait for the executor to terminate, according to the value of the
|
||||||
|
* {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"} property.
|
||||||
|
*/
|
||||||
|
private void awaitTerminationIfNecessary() {
|
||||||
|
if (this.awaitTerminationSeconds > 0) {
|
||||||
|
try {
|
||||||
|
if (!this.executor.awaitTermination(this.awaitTerminationSeconds, TimeUnit.SECONDS)) {
|
||||||
|
if (logger.isWarnEnabled()) {
|
||||||
|
logger.warn("Timed out while waiting for executor" +
|
||||||
|
(this.beanName != null ? " '" + this.beanName + "'" : "") + " to terminate");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (InterruptedException ex) {
|
||||||
|
if (logger.isWarnEnabled()) {
|
||||||
|
logger.warn("Interrupted while waiting for executor" +
|
||||||
|
(this.beanName != null ? " '" + this.beanName + "'" : "") + " to terminate");
|
||||||
|
}
|
||||||
|
Thread.currentThread().interrupt();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -126,7 +126,7 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||||
* <p>Default is "false", exposing the raw executor as bean reference.
|
* <p>Default is "false", exposing the raw executor as bean reference.
|
||||||
* Switch this flag to "true" to strictly prevent clients from
|
* Switch this flag to "true" to strictly prevent clients from
|
||||||
* modifying the executor's configuration.
|
* modifying the executor's configuration.
|
||||||
* @see java.util.concurrent.Executors#unconfigurableScheduledExecutorService
|
* @see java.util.concurrent.Executors#unconfigurableExecutorService
|
||||||
*/
|
*/
|
||||||
public void setExposeUnconfigurableExecutor(boolean exposeUnconfigurableExecutor) {
|
public void setExposeUnconfigurableExecutor(boolean exposeUnconfigurableExecutor) {
|
||||||
this.exposeUnconfigurableExecutor = exposeUnconfigurableExecutor;
|
this.exposeUnconfigurableExecutor = exposeUnconfigurableExecutor;
|
||||||
|
|
@ -137,9 +137,8 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||||
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
|
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
|
||||||
|
|
||||||
BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);
|
BlockingQueue<Runnable> queue = createQueue(this.queueCapacity);
|
||||||
ThreadPoolExecutor executor = new ThreadPoolExecutor(
|
ThreadPoolExecutor executor = createExecutor(this.corePoolSize, this.maxPoolSize,
|
||||||
this.corePoolSize, this.maxPoolSize, this.keepAliveSeconds, TimeUnit.SECONDS,
|
this.keepAliveSeconds, queue, threadFactory, rejectedExecutionHandler);
|
||||||
queue, threadFactory, rejectedExecutionHandler);
|
|
||||||
if (this.allowCoreThreadTimeOut) {
|
if (this.allowCoreThreadTimeOut) {
|
||||||
executor.allowCoreThreadTimeOut(true);
|
executor.allowCoreThreadTimeOut(true);
|
||||||
}
|
}
|
||||||
|
|
@ -151,6 +150,27 @@ public class ThreadPoolExecutorFactoryBean extends ExecutorConfigurationSupport
|
||||||
return executor;
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of {@link ThreadPoolExecutor} or a subclass thereof.
|
||||||
|
* <p>The default implementation creates a standard {@link ThreadPoolExecutor}.
|
||||||
|
* Can be overridden to provide custom {@link ThreadPoolExecutor} subclasses.
|
||||||
|
* @param corePoolSize the specified core pool size
|
||||||
|
* @param maxPoolSize the specified maximum pool size
|
||||||
|
* @param keepAliveSeconds the specified keep-alive time in seconds
|
||||||
|
* @param queue the BlockingQueue to use
|
||||||
|
* @param threadFactory the ThreadFactory to use
|
||||||
|
* @param rejectedExecutionHandler the RejectedExecutionHandler to use
|
||||||
|
* @return a new ThreadPoolExecutor instance
|
||||||
|
* @see #afterPropertiesSet()
|
||||||
|
*/
|
||||||
|
protected ThreadPoolExecutor createExecutor(
|
||||||
|
int corePoolSize, int maxPoolSize, int keepAliveSeconds, BlockingQueue<Runnable> queue,
|
||||||
|
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
|
||||||
|
|
||||||
|
return new ThreadPoolExecutor(corePoolSize, maxPoolSize,
|
||||||
|
keepAliveSeconds, TimeUnit.SECONDS, queue, threadFactory, rejectedExecutionHandler);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the BlockingQueue to use for the ThreadPoolExecutor.
|
* Create the BlockingQueue to use for the ThreadPoolExecutor.
|
||||||
* <p>A LinkedBlockingQueue instance will be created for a positive
|
* <p>A LinkedBlockingQueue instance will be created for a positive
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
/*
|
||||||
|
* 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.scheduling.config;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.context.ApplicationContextAware;
|
||||||
|
import org.springframework.context.ApplicationListener;
|
||||||
|
import org.springframework.context.event.ContextRefreshedEvent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* {@link ScheduledTaskRegistrar} subclass that redirects the actual scheduling
|
||||||
|
* of tasks to the {@link ContextRefreshedEvent} callback. Falls back to regular
|
||||||
|
* {@code ScheduledTaskRegistrar} behavior when not running within an ApplicationContext.
|
||||||
|
*
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
* @since 3.2.1
|
||||||
|
*/
|
||||||
|
public class ContextLifecycleScheduledTaskRegistrar extends ScheduledTaskRegistrar
|
||||||
|
implements ApplicationContextAware, ApplicationListener<ContextRefreshedEvent> {
|
||||||
|
|
||||||
|
private ApplicationContext applicationContext;
|
||||||
|
|
||||||
|
|
||||||
|
public void setApplicationContext(ApplicationContext applicationContext) {
|
||||||
|
this.applicationContext = applicationContext;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we're running within an ApplicationContext, don't schedule the tasks
|
||||||
|
* right here; wait for this context's ContextRefreshedEvent instead.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void afterPropertiesSet() {
|
||||||
|
if (this.applicationContext == null) {
|
||||||
|
scheduleTasks();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually schedule the tasks at the right time of the context lifecycle,
|
||||||
|
* if we're running within an ApplicationContext.
|
||||||
|
*/
|
||||||
|
public void onApplicationEvent(ContextRefreshedEvent event) {
|
||||||
|
if (event.getApplicationContext() != this.applicationContext) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
scheduleTasks();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -274,11 +274,19 @@ public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean
|
||||||
(this.triggerTasks != null && !this.triggerTasks.isEmpty());
|
(this.triggerTasks != null && !this.triggerTasks.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calls {@link #scheduleTasks()} at bean construction time.
|
||||||
|
*/
|
||||||
|
public void afterPropertiesSet() {
|
||||||
|
scheduleTasks();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Schedule all registered tasks against the underlying {@linkplain
|
* Schedule all registered tasks against the underlying {@linkplain
|
||||||
* #setTaskScheduler(TaskScheduler) task scheduler}.
|
* #setTaskScheduler(TaskScheduler) task scheduler}.
|
||||||
*/
|
*/
|
||||||
public void afterPropertiesSet() {
|
protected void scheduleTasks() {
|
||||||
long now = System.currentTimeMillis();
|
long now = System.currentTimeMillis();
|
||||||
|
|
||||||
if (this.taskScheduler == null) {
|
if (this.taskScheduler == null) {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -38,8 +38,10 @@ import org.w3c.dom.NodeList;
|
||||||
public class ScheduledTasksBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
public class ScheduledTasksBeanDefinitionParser extends AbstractSingleBeanDefinitionParser {
|
||||||
|
|
||||||
private static final String ELEMENT_SCHEDULED = "scheduled";
|
private static final String ELEMENT_SCHEDULED = "scheduled";
|
||||||
|
|
||||||
private static final long ZERO_INITIAL_DELAY = 0;
|
private static final long ZERO_INITIAL_DELAY = 0;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean shouldGenerateId() {
|
protected boolean shouldGenerateId() {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -47,7 +49,7 @@ public class ScheduledTasksBeanDefinitionParser extends AbstractSingleBeanDefini
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getBeanClassName(Element element) {
|
protected String getBeanClassName(Element element) {
|
||||||
return "org.springframework.scheduling.config.ScheduledTaskRegistrar";
|
return "org.springframework.scheduling.config.ContextLifecycleScheduledTaskRegistrar";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -31,8 +31,8 @@ import org.springframework.util.Assert;
|
||||||
* <emphasis>completion</emphasis> time). To measure the interval between the
|
* <emphasis>completion</emphasis> time). To measure the interval between the
|
||||||
* scheduled <emphasis>start</emphasis> time of each execution instead, set the
|
* scheduled <emphasis>start</emphasis> time of each execution instead, set the
|
||||||
* 'fixedRate' property to {@code true}.
|
* 'fixedRate' property to {@code true}.
|
||||||
* <p>
|
*
|
||||||
* Note that the TaskScheduler interface already defines methods for scheduling
|
* <p>Note that the TaskScheduler interface already defines methods for scheduling
|
||||||
* tasks at fixed-rate or with fixed-delay. Both also support an optional value
|
* tasks at fixed-rate or with fixed-delay. Both also support an optional value
|
||||||
* for the initial delay. Those methods should be used directly whenever
|
* for the initial delay. Those methods should be used directly whenever
|
||||||
* possible. The value of this Trigger implementation is that it can be used
|
* possible. The value of this Trigger implementation is that it can be used
|
||||||
|
|
@ -68,7 +68,7 @@ public class PeriodicTrigger implements Trigger {
|
||||||
*/
|
*/
|
||||||
public PeriodicTrigger(long period, TimeUnit timeUnit) {
|
public PeriodicTrigger(long period, TimeUnit timeUnit) {
|
||||||
Assert.isTrue(period >= 0, "period must not be negative");
|
Assert.isTrue(period >= 0, "period must not be negative");
|
||||||
this.timeUnit = (timeUnit != null) ? timeUnit : TimeUnit.MILLISECONDS;
|
this.timeUnit = (timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS);
|
||||||
this.period = this.timeUnit.toMillis(period);
|
this.period = this.timeUnit.toMillis(period);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -91,6 +91,7 @@ public class PeriodicTrigger implements Trigger {
|
||||||
this.fixedRate = fixedRate;
|
this.fixedRate = fixedRate;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the time after which a task should run again.
|
* Returns the time after which a task should run again.
|
||||||
*/
|
*/
|
||||||
|
|
@ -104,6 +105,7 @@ public class PeriodicTrigger implements Trigger {
|
||||||
return new Date(triggerContext.lastCompletionTime().getTime() + this.period);
|
return new Date(triggerContext.lastCompletionTime().getTime() + this.period);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (this == obj) {
|
if (this == obj) {
|
||||||
|
|
@ -113,16 +115,12 @@ public class PeriodicTrigger implements Trigger {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
PeriodicTrigger other = (PeriodicTrigger) obj;
|
PeriodicTrigger other = (PeriodicTrigger) obj;
|
||||||
return this.fixedRate == other.fixedRate
|
return (this.fixedRate == other.fixedRate && this.initialDelay == other.initialDelay && this.period == other.period);
|
||||||
&& this.initialDelay == other.initialDelay
|
|
||||||
&& this.period == other.period;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
return (this.fixedRate ? 17 : 29) +
|
return (this.fixedRate ? 17 : 29) + (int) (37 * this.period) + (int) (41 * this.initialDelay);
|
||||||
(int) (37 * this.period) +
|
|
||||||
(int) (41 * this.initialDelay);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,11 @@ package org.springframework.validation;
|
||||||
|
|
||||||
import java.beans.PropertyEditor;
|
import java.beans.PropertyEditor;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
@ -141,7 +145,7 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||||
|
|
||||||
private BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor();
|
private BindingErrorProcessor bindingErrorProcessor = new DefaultBindingErrorProcessor();
|
||||||
|
|
||||||
private Validator validator;
|
private final List<Validator> validators = new ArrayList<Validator>();
|
||||||
|
|
||||||
private ConversionService conversionService;
|
private ConversionService conversionService;
|
||||||
|
|
||||||
|
|
@ -493,21 +497,58 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the Validator to apply after each binding step.
|
* Set the Validator to apply after each binding step.
|
||||||
|
* @see #addValidators(Validator...)
|
||||||
|
* @see #replaceValidators(Validator...)
|
||||||
*/
|
*/
|
||||||
public void setValidator(Validator validator) {
|
public void setValidator(Validator validator) {
|
||||||
if (validator != null && (getTarget() != null && !validator.supports(getTarget().getClass()))) {
|
assertValidators(validator);
|
||||||
throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + getTarget());
|
this.validators.clear();
|
||||||
|
this.validators.add(validator);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertValidators(Validator... validators) {
|
||||||
|
Assert.notNull(validators, "Validators required");
|
||||||
|
for (Validator validator : validators) {
|
||||||
|
if (validator != null && (getTarget() != null && !validator.supports(getTarget().getClass()))) {
|
||||||
|
throw new IllegalStateException("Invalid target for Validator [" + validator + "]: " + getTarget());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.validator = validator;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Validator to apply after each binding step, if any.
|
* Add Validators to apply after each binding step.
|
||||||
|
* @see #setValidator(Validator)
|
||||||
|
* @see #replaceValidators(Validator...)
|
||||||
*/
|
*/
|
||||||
public Validator getValidator() {
|
public void addValidators(Validator... validators) {
|
||||||
return this.validator;
|
assertValidators(validators);
|
||||||
|
this.validators.addAll(Arrays.asList(validators));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replace the Validators to apply after each binding step.
|
||||||
|
* @see #setValidator(Validator)
|
||||||
|
* @see #addValidators(Validator...)
|
||||||
|
*/
|
||||||
|
public void replaceValidators(Validator... validators) {
|
||||||
|
assertValidators(validators);
|
||||||
|
this.validators.clear();
|
||||||
|
this.validators.addAll(Arrays.asList(validators));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the primary Validator to apply after each binding step, if any.
|
||||||
|
*/
|
||||||
|
public Validator getValidator() {
|
||||||
|
return this.validators.size() > 0 ? this.validators.get(0) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the Validators to apply after data binding.
|
||||||
|
*/
|
||||||
|
public List<Validator> getValidators() {
|
||||||
|
return Collections.unmodifiableList(this.validators);
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
// Implementation of PropertyEditorRegistry/TypeConverter interface
|
// Implementation of PropertyEditorRegistry/TypeConverter interface
|
||||||
|
|
@ -708,28 +749,31 @@ public class DataBinder implements PropertyEditorRegistry, TypeConverter {
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the specified Validator, if any.
|
* Invoke the specified Validators, if any.
|
||||||
* @see #setValidator(Validator)
|
* @see #setValidator(Validator)
|
||||||
* @see #getBindingResult()
|
* @see #getBindingResult()
|
||||||
*/
|
*/
|
||||||
public void validate() {
|
public void validate() {
|
||||||
this.validator.validate(getTarget(), getBindingResult());
|
for (Validator validator : this.validators) {
|
||||||
|
validator.validate(getTarget(), getBindingResult());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Invoke the specified Validator, if any, with the given validation hints.
|
* Invoke the specified Validators, if any, with the given validation hints.
|
||||||
* <p>Note: Validation hints may get ignored by the actual target Validator.
|
* <p>Note: Validation hints may get ignored by the actual target Validator.
|
||||||
* @param validationHints one or more hint objects to be passed to a {@link SmartValidator}
|
* @param validationHints one or more hint objects to be passed to a {@link SmartValidator}
|
||||||
* @see #setValidator(Validator)
|
* @see #setValidator(Validator)
|
||||||
* @see SmartValidator#validate(Object, Errors, Object...)
|
* @see SmartValidator#validate(Object, Errors, Object...)
|
||||||
*/
|
*/
|
||||||
public void validate(Object... validationHints) {
|
public void validate(Object... validationHints) {
|
||||||
Validator validator = getValidator();
|
for (Validator validator : getValidators()) {
|
||||||
if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) {
|
if (!ObjectUtils.isEmpty(validationHints) && validator instanceof SmartValidator) {
|
||||||
((SmartValidator) validator).validate(getTarget(), getBindingResult(), validationHints);
|
((SmartValidator) validator).validate(getTarget(), getBindingResult(), validationHints);
|
||||||
}
|
}
|
||||||
else if (validator != null) {
|
else if (validator != null) {
|
||||||
validator.validate(getTarget(), getBindingResult());
|
validator.validate(getTarget(), getBindingResult());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -99,7 +99,8 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
processConstraintViolations(this.targetValidator.validate(target, groups.toArray(new Class[groups.size()])), errors);
|
processConstraintViolations(
|
||||||
|
this.targetValidator.validate(target, groups.toArray(new Class[groups.size()])), errors);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -114,10 +115,11 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
||||||
FieldError fieldError = errors.getFieldError(field);
|
FieldError fieldError = errors.getFieldError(field);
|
||||||
if (fieldError == null || !fieldError.isBindingFailure()) {
|
if (fieldError == null || !fieldError.isBindingFailure()) {
|
||||||
try {
|
try {
|
||||||
String errorCode = violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();
|
ConstraintDescriptor<?> cd = violation.getConstraintDescriptor();
|
||||||
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, violation.getConstraintDescriptor());
|
String errorCode = cd.getAnnotation().annotationType().getSimpleName();
|
||||||
|
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, cd);
|
||||||
if (errors instanceof BindingResult) {
|
if (errors instanceof BindingResult) {
|
||||||
// can do custom FieldError registration with invalid value from ConstraintViolation,
|
// Can do custom FieldError registration with invalid value from ConstraintViolation,
|
||||||
// as necessary for Hibernate Validator compatibility (non-indexed set path in field)
|
// as necessary for Hibernate Validator compatibility (non-indexed set path in field)
|
||||||
BindingResult bindingResult = (BindingResult) errors;
|
BindingResult bindingResult = (BindingResult) errors;
|
||||||
String nestedField = bindingResult.getNestedPath() + field;
|
String nestedField = bindingResult.getNestedPath() + field;
|
||||||
|
|
@ -128,8 +130,9 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object invalidValue = violation.getInvalidValue();
|
Object invalidValue = violation.getInvalidValue();
|
||||||
if (!"".equals(field) && invalidValue == violation.getLeafBean()) {
|
if (field.contains(".") && !field.contains("[]")) {
|
||||||
// bean constraint with property path: retrieve the actual property value
|
// Possibly a bean constraint with property path: retrieve the actual property value.
|
||||||
|
// However, explicitly avoid this for "address[]" style paths that we can't handle.
|
||||||
invalidValue = bindingResult.getRawFieldValue(field);
|
invalidValue = bindingResult.getRawFieldValue(field);
|
||||||
}
|
}
|
||||||
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
|
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,39 @@
|
||||||
]]></xsd:documentation>
|
]]></xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:attribute>
|
</xsd:attribute>
|
||||||
|
<xsd:attribute name="mode" default="proxy">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation><![CDATA[
|
||||||
|
Should annotated beans be proxied using Spring's AOP framework,
|
||||||
|
or should they rather be weaved with an AspectJ async execution aspect?
|
||||||
|
|
||||||
|
AspectJ weaving requires spring-aspects.jar on the classpath,
|
||||||
|
as well as load-time weaving (or compile-time weaving) enabled.
|
||||||
|
|
||||||
|
Note: The weaving-based aspect requires the @Async annotation to be
|
||||||
|
defined on the concrete class. Annotations in interfaces will not work
|
||||||
|
in that case (they will rather only work with interface-based proxies)!
|
||||||
|
]]></xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:string">
|
||||||
|
<xsd:enumeration value="proxy"/>
|
||||||
|
<xsd:enumeration value="aspectj"/>
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:attribute>
|
||||||
|
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation><![CDATA[
|
||||||
|
Are class-based (CGLIB) proxies to be created? By default, standard
|
||||||
|
Java interface-based proxies are created.
|
||||||
|
|
||||||
|
Note: Class-based proxies require the @Async annotation to be defined
|
||||||
|
on the concrete class. Annotations in interfaces will not work in
|
||||||
|
that case (they will rather only work with interface-based proxies)!
|
||||||
|
]]></xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
</xsd:attribute>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,39 @@
|
||||||
]]></xsd:documentation>
|
]]></xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:attribute>
|
</xsd:attribute>
|
||||||
|
<xsd:attribute name="mode" default="proxy">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation><![CDATA[
|
||||||
|
Should annotated beans be proxied using Spring's AOP framework,
|
||||||
|
or should they rather be weaved with an AspectJ async execution aspect?
|
||||||
|
|
||||||
|
AspectJ weaving requires spring-aspects.jar on the classpath,
|
||||||
|
as well as load-time weaving (or compile-time weaving) enabled.
|
||||||
|
|
||||||
|
Note: The weaving-based aspect requires the @Async annotation to be
|
||||||
|
defined on the concrete class. Annotations in interfaces will not work
|
||||||
|
in that case (they will rather only work with interface-based proxies)!
|
||||||
|
]]></xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
<xsd:simpleType>
|
||||||
|
<xsd:restriction base="xsd:string">
|
||||||
|
<xsd:enumeration value="proxy"/>
|
||||||
|
<xsd:enumeration value="aspectj"/>
|
||||||
|
</xsd:restriction>
|
||||||
|
</xsd:simpleType>
|
||||||
|
</xsd:attribute>
|
||||||
|
<xsd:attribute name="proxy-target-class" type="xsd:boolean" default="false">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation><![CDATA[
|
||||||
|
Are class-based (CGLIB) proxies to be created? By default, standard
|
||||||
|
Java interface-based proxies are created.
|
||||||
|
|
||||||
|
Note: Class-based proxies require the @Async annotation to be defined
|
||||||
|
on the concrete class. Annotations in interfaces will not work in
|
||||||
|
that case (they will rather only work with interface-based proxies)!
|
||||||
|
]]></xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
</xsd:attribute>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,8 +17,10 @@
|
||||||
package org.springframework.context.annotation;
|
package org.springframework.context.annotation;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.factory.FactoryBean;
|
import org.springframework.beans.factory.FactoryBean;
|
||||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
|
@ -27,7 +29,7 @@ import org.springframework.context.annotation6.ComponentForScanning;
|
||||||
import org.springframework.context.annotation6.ConfigForScanning;
|
import org.springframework.context.annotation6.ConfigForScanning;
|
||||||
import org.springframework.context.annotation6.Jsr330NamedForScanning;
|
import org.springframework.context.annotation6.Jsr330NamedForScanning;
|
||||||
|
|
||||||
import static java.lang.String.*;
|
import static java.lang.String.format;
|
||||||
import static org.hamcrest.Matchers.*;
|
import static org.hamcrest.Matchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
import static org.springframework.util.StringUtils.*;
|
import static org.springframework.util.StringUtils.*;
|
||||||
|
|
@ -120,13 +122,14 @@ public class AnnotationConfigApplicationContextTests {
|
||||||
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
|
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext(Config.class);
|
||||||
|
|
||||||
// attempt to retrieve a bean that does not exist
|
// attempt to retrieve a bean that does not exist
|
||||||
Class<?> targetType = java.util.regex.Pattern.class;
|
Class<?> targetType = Pattern.class;
|
||||||
try {
|
try {
|
||||||
Object bean = context.getBean(targetType);
|
Object bean = context.getBean(targetType);
|
||||||
fail("should have thrown NoSuchBeanDefinitionException, instead got: " + bean);
|
fail("should have thrown NoSuchBeanDefinitionException, instead got: " + bean);
|
||||||
} catch (NoSuchBeanDefinitionException ex) {
|
}
|
||||||
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
assertThat(ex.getMessage(), containsString(
|
assertThat(ex.getMessage(), containsString(
|
||||||
format("No unique bean of type [%s] is defined", targetType.getName())));
|
format("No qualifying bean of type [%s] is defined", targetType.getName())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,10 +140,11 @@ public class AnnotationConfigApplicationContextTests {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
context.getBean(TestBean.class);
|
context.getBean(TestBean.class);
|
||||||
} catch (RuntimeException ex) {
|
}
|
||||||
|
catch (NoSuchBeanDefinitionException ex) {
|
||||||
assertThat(ex.getMessage(),
|
assertThat(ex.getMessage(),
|
||||||
allOf(
|
allOf(
|
||||||
containsString("No unique bean of type [" + TestBean.class.getName() + "] is defined"),
|
containsString("No qualifying bean of type [" + TestBean.class.getName() + "] is defined"),
|
||||||
containsString("tb1"),
|
containsString("tb1"),
|
||||||
containsString("tb2")
|
containsString("tb2")
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,16 +16,21 @@
|
||||||
|
|
||||||
package org.springframework.context.annotation;
|
package org.springframework.context.annotation;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.support.GenericXmlApplicationContext;
|
import org.springframework.context.support.GenericXmlApplicationContext;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Chris Beams
|
||||||
|
* @author Juergen Hoeller
|
||||||
|
*/
|
||||||
public class DestroyMethodInferenceTests {
|
public class DestroyMethodInferenceTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -39,6 +44,7 @@ public class DestroyMethodInferenceTests {
|
||||||
WithInheritedCloseMethod c4 = ctx.getBean("c4", WithInheritedCloseMethod.class);
|
WithInheritedCloseMethod c4 = ctx.getBean("c4", WithInheritedCloseMethod.class);
|
||||||
WithInheritedCloseMethod c5 = ctx.getBean("c5", WithInheritedCloseMethod.class);
|
WithInheritedCloseMethod c5 = ctx.getBean("c5", WithInheritedCloseMethod.class);
|
||||||
WithNoCloseMethod c6 = ctx.getBean("c6", WithNoCloseMethod.class);
|
WithNoCloseMethod c6 = ctx.getBean("c6", WithNoCloseMethod.class);
|
||||||
|
WithLocalShutdownMethod c7 = ctx.getBean("c7", WithLocalShutdownMethod.class);
|
||||||
|
|
||||||
assertThat(c0.closed, is(false));
|
assertThat(c0.closed, is(false));
|
||||||
assertThat(c1.closed, is(false));
|
assertThat(c1.closed, is(false));
|
||||||
|
|
@ -47,6 +53,7 @@ public class DestroyMethodInferenceTests {
|
||||||
assertThat(c4.closed, is(false));
|
assertThat(c4.closed, is(false));
|
||||||
assertThat(c5.closed, is(false));
|
assertThat(c5.closed, is(false));
|
||||||
assertThat(c6.closed, is(false));
|
assertThat(c6.closed, is(false));
|
||||||
|
assertThat(c7.closed, is(false));
|
||||||
ctx.close();
|
ctx.close();
|
||||||
assertThat("c0", c0.closed, is(true));
|
assertThat("c0", c0.closed, is(true));
|
||||||
assertThat("c1", c1.closed, is(true));
|
assertThat("c1", c1.closed, is(true));
|
||||||
|
|
@ -55,6 +62,7 @@ public class DestroyMethodInferenceTests {
|
||||||
assertThat("c4", c4.closed, is(true));
|
assertThat("c4", c4.closed, is(true));
|
||||||
assertThat("c5", c5.closed, is(true));
|
assertThat("c5", c5.closed, is(true));
|
||||||
assertThat("c6", c6.closed, is(false));
|
assertThat("c6", c6.closed, is(false));
|
||||||
|
assertThat("c7", c7.closed, is(true));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
@ -121,6 +129,11 @@ public class DestroyMethodInferenceTests {
|
||||||
public WithNoCloseMethod c6() {
|
public WithNoCloseMethod c6() {
|
||||||
return new WithNoCloseMethod();
|
return new WithNoCloseMethod();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public WithLocalShutdownMethod c7() {
|
||||||
|
return new WithLocalShutdownMethod();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -149,4 +162,12 @@ public class DestroyMethodInferenceTests {
|
||||||
static class WithNoCloseMethod {
|
static class WithNoCloseMethod {
|
||||||
boolean closed = false;
|
boolean closed = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static class WithLocalShutdownMethod {
|
||||||
|
boolean closed = false;
|
||||||
|
public void shutdown() {
|
||||||
|
closed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
* 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.support;
|
||||||
|
|
||||||
|
import static java.lang.String.format;
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
|
||||||
|
import java.security.AccessControlException;
|
||||||
|
import java.security.Permission;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.core.env.AbstractEnvironment;
|
||||||
|
import org.springframework.core.env.StandardEnvironmentTests;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests integration between Environment and SecurityManagers. See SPR-9970.
|
||||||
|
*
|
||||||
|
* @author Chris Beams
|
||||||
|
*/
|
||||||
|
public class EnvironmentSecurityManagerIntegrationTests {
|
||||||
|
|
||||||
|
private SecurityManager originalSecurityManager;
|
||||||
|
private Map<String, String> env;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setUp() {
|
||||||
|
originalSecurityManager = System.getSecurityManager();
|
||||||
|
env = StandardEnvironmentTests.getModifiableSystemEnvironment();
|
||||||
|
env.put(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME, "p1");
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void tearDown() {
|
||||||
|
env.remove(AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME);
|
||||||
|
System.setSecurityManager(originalSecurityManager);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void securityManagerDisallowsAccessToSystemEnvironmentButAllowsAccessToIndividualKeys() {
|
||||||
|
SecurityManager securityManager = new SecurityManager() {
|
||||||
|
@Override
|
||||||
|
public void checkPermission(Permission perm) {
|
||||||
|
// disallowing access to System#getenv means that our
|
||||||
|
// ReadOnlySystemAttributesMap will come into play.
|
||||||
|
if ("getenv.*".equals(perm.getName())) {
|
||||||
|
throw new AccessControlException(
|
||||||
|
"Accessing the system environment is disallowed");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
System.setSecurityManager(securityManager);
|
||||||
|
|
||||||
|
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||||
|
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(bf);
|
||||||
|
reader.register(C1.class);
|
||||||
|
assertThat(bf.containsBean("c1"), is(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void securityManagerDisallowsAccessToSystemEnvironmentAndDisallowsAccessToIndividualKey() {
|
||||||
|
SecurityManager securityManager = new SecurityManager() {
|
||||||
|
@Override
|
||||||
|
public void checkPermission(Permission perm) {
|
||||||
|
// disallowing access to System#getenv means that our
|
||||||
|
// ReadOnlySystemAttributesMap will come into play.
|
||||||
|
if ("getenv.*".equals(perm.getName())) {
|
||||||
|
throw new AccessControlException(
|
||||||
|
"Accessing the system environment is disallowed");
|
||||||
|
}
|
||||||
|
// disallowing access to the spring.profiles.active property means that
|
||||||
|
// the BeanDefinitionReader won't be able to determine which profiles are
|
||||||
|
// active. We should see an INFO-level message in the console about this
|
||||||
|
// and as a result, any components marked with a non-default profile will
|
||||||
|
// be ignored.
|
||||||
|
if (("getenv."+AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME).equals(perm.getName())) {
|
||||||
|
throw new AccessControlException(
|
||||||
|
format("Accessing system environment variable [%s] is disallowed",
|
||||||
|
AbstractEnvironment.ACTIVE_PROFILES_PROPERTY_NAME));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
System.setSecurityManager(securityManager);
|
||||||
|
|
||||||
|
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||||
|
AnnotatedBeanDefinitionReader reader = new AnnotatedBeanDefinitionReader(bf);
|
||||||
|
reader.register(C1.class);
|
||||||
|
assertThat(bf.containsBean("c1"), is(false));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component("c1")
|
||||||
|
@Profile("p1")
|
||||||
|
static class C1 {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -340,6 +340,17 @@ public class ResourceBundleMessageSourceTests extends TestCase {
|
||||||
assertEquals(0, filenames.size());
|
assertEquals(0, filenames.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testMessageSourceResourceBundle() {
|
||||||
|
ResourceBundleMessageSource ms = new ResourceBundleMessageSource();
|
||||||
|
ms.setBasename("org/springframework/context/support/messages");
|
||||||
|
MessageSourceResourceBundle rbe = new MessageSourceResourceBundle(ms, Locale.ENGLISH);
|
||||||
|
assertEquals("message1", rbe.getString("code1"));
|
||||||
|
assertTrue(rbe.containsKey("code1"));
|
||||||
|
MessageSourceResourceBundle rbg = new MessageSourceResourceBundle(ms, Locale.GERMAN);
|
||||||
|
assertEquals("nachricht2", rbg.getString("code2"));
|
||||||
|
assertTrue(rbg.containsKey("code2"));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void tearDown() throws Exception {
|
protected void tearDown() throws Exception {
|
||||||
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_16) {
|
if (JdkVersion.getMajorJavaVersion() >= JdkVersion.JAVA_16) {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -30,10 +30,10 @@ import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||||
import org.springframework.format.datetime.DateFormatterRegistrar;
|
|
||||||
import org.springframework.format.support.FormattingConversionService;
|
import org.springframework.format.support.FormattingConversionService;
|
||||||
import org.springframework.validation.DataBinder;
|
import org.springframework.validation.DataBinder;
|
||||||
|
|
||||||
|
|
@ -186,6 +186,14 @@ public class DateFormattingTests {
|
||||||
assertEquals("10/31/09", binder.getBindingResult().getFieldValue("children[0].dateAnnotated"));
|
assertEquals("10/31/09", binder.getBindingResult().getFieldValue("children[0].dateAnnotated"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dateToString() throws Exception {
|
||||||
|
Date date = new Date();
|
||||||
|
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
|
||||||
|
String expected = new DateFormatter().print(date, Locale.US);
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static class SimpleDateBean {
|
private static class SimpleDateBean {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -35,6 +35,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.beans.MutablePropertyValues;
|
import org.springframework.beans.MutablePropertyValues;
|
||||||
import org.springframework.context.i18n.LocaleContextHolder;
|
import org.springframework.context.i18n.LocaleContextHolder;
|
||||||
|
import org.springframework.core.convert.TypeDescriptor;
|
||||||
import org.springframework.core.convert.support.DefaultConversionService;
|
import org.springframework.core.convert.support.DefaultConversionService;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||||
|
|
@ -46,6 +47,7 @@ import static org.junit.Assert.*;
|
||||||
/**
|
/**
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
public class JodaTimeFormattingTests {
|
public class JodaTimeFormattingTests {
|
||||||
|
|
||||||
|
|
@ -456,6 +458,14 @@ public class JodaTimeFormattingTests {
|
||||||
assertEquals("2009-10-31T07:00:00.000-05:00", binder.getBindingResult().getFieldValue("mutableDateTimeAnnotated"));
|
assertEquals("2009-10-31T07:00:00.000-05:00", binder.getBindingResult().getFieldValue("mutableDateTimeAnnotated"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void dateToString() throws Exception {
|
||||||
|
Date date = new Date();
|
||||||
|
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
|
||||||
|
String expected = JodaTimeContextHolder.getFormatter(org.joda.time.format.DateTimeFormat.shortDateTime(), Locale.US).print(new DateTime(date));
|
||||||
|
assertEquals(expected, actual);
|
||||||
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
private static class JodaTimeBean {
|
private static class JodaTimeBean {
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
* 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
|
* use this file except in compliance with the License. You may obtain a copy of
|
||||||
|
|
@ -16,11 +16,13 @@
|
||||||
|
|
||||||
package org.springframework.jmx.export.assembler;
|
package org.springframework.jmx.export.assembler;
|
||||||
|
|
||||||
|
import javax.management.MBeanOperationInfo;
|
||||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||||
import javax.management.modelmbean.ModelMBeanInfo;
|
import javax.management.modelmbean.ModelMBeanInfo;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
|
* @author David Boden
|
||||||
*/
|
*/
|
||||||
public class MethodNameBasedMBeanInfoAssemblerTests extends AbstractJmxAssemblerTests {
|
public class MethodNameBasedMBeanInfoAssemblerTests extends AbstractJmxAssemblerTests {
|
||||||
|
|
||||||
|
|
@ -56,6 +58,13 @@ public class MethodNameBasedMBeanInfoAssemblerTests extends AbstractJmxAssembler
|
||||||
assertFalse(attr.isWritable());
|
assertFalse(attr.isWritable());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void testSetNameParameterIsNamed() throws Exception {
|
||||||
|
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||||
|
|
||||||
|
MBeanOperationInfo operationSetAge = info.getOperation("setName");
|
||||||
|
assertEquals("name", operationSetAge.getSignature()[0].getName());
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String getApplicationContextPath() {
|
protected String getApplicationContextPath() {
|
||||||
return "org/springframework/jmx/export/assembler/methodNameAssembler.xml";
|
return "org/springframework/jmx/export/assembler/methodNameAssembler.xml";
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,11 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.scheduling.concurrent;
|
package org.springframework.scheduling.concurrent;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
|
|
@ -29,6 +24,7 @@ import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
import org.junit.After;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
|
@ -36,6 +32,8 @@ import org.springframework.scheduling.Trigger;
|
||||||
import org.springframework.scheduling.TriggerContext;
|
import org.springframework.scheduling.TriggerContext;
|
||||||
import org.springframework.util.ErrorHandler;
|
import org.springframework.util.ErrorHandler;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Mark Fisher
|
* @author Mark Fisher
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
@ -44,7 +42,6 @@ public class ThreadPoolTaskSchedulerTests {
|
||||||
|
|
||||||
private static final String THREAD_NAME_PREFIX = "test-";
|
private static final String THREAD_NAME_PREFIX = "test-";
|
||||||
|
|
||||||
|
|
||||||
private final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
private final ThreadPoolTaskScheduler scheduler = new ThreadPoolTaskScheduler();
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -54,6 +51,11 @@ public class ThreadPoolTaskSchedulerTests {
|
||||||
scheduler.afterPropertiesSet();
|
scheduler.afterPropertiesSet();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
public void shutdownScheduler() {
|
||||||
|
scheduler.destroy();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// test methods
|
// test methods
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -30,6 +30,7 @@ import javax.validation.Constraint;
|
||||||
import javax.validation.ConstraintValidator;
|
import javax.validation.ConstraintValidator;
|
||||||
import javax.validation.ConstraintValidatorContext;
|
import javax.validation.ConstraintValidatorContext;
|
||||||
import javax.validation.ConstraintViolation;
|
import javax.validation.ConstraintViolation;
|
||||||
|
import javax.validation.Payload;
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
|
@ -37,6 +38,7 @@ import org.hibernate.validator.HibernateValidator;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.validation.BeanPropertyBindingResult;
|
import org.springframework.validation.BeanPropertyBindingResult;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
import org.springframework.validation.FieldError;
|
import org.springframework.validation.FieldError;
|
||||||
import org.springframework.validation.ObjectError;
|
import org.springframework.validation.ObjectError;
|
||||||
|
|
||||||
|
|
@ -193,6 +195,18 @@ public class ValidatorFactoryTests {
|
||||||
System.out.println(fieldError.getDefaultMessage());
|
System.out.println(fieldError.getDefaultMessage());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testInnerBeanValidation() throws Exception {
|
||||||
|
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||||
|
validator.afterPropertiesSet();
|
||||||
|
|
||||||
|
MainBean mainBean = new MainBean();
|
||||||
|
Errors errors = new BeanPropertyBindingResult(mainBean, "mainBean");
|
||||||
|
validator.validate(mainBean, errors);
|
||||||
|
Object rejected = errors.getFieldValue("inner.value");
|
||||||
|
assertNull(rejected);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@NameAddressValid
|
@NameAddressValid
|
||||||
public static class ValidPerson {
|
public static class ValidPerson {
|
||||||
|
|
@ -242,7 +256,6 @@ public class ValidatorFactoryTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class ValidAddress {
|
public static class ValidAddress {
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|
@ -257,7 +270,6 @@ public class ValidatorFactoryTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Target(ElementType.TYPE)
|
@Target(ElementType.TYPE)
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Constraint(validatedBy = NameAddressValidator.class)
|
@Constraint(validatedBy = NameAddressValidator.class)
|
||||||
|
|
@ -270,7 +282,6 @@ public class ValidatorFactoryTests {
|
||||||
Class<?>[] payload() default {};
|
Class<?>[] payload() default {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
|
public static class NameAddressValidator implements ConstraintValidator<NameAddressValid, ValidPerson> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -283,4 +294,53 @@ public class ValidatorFactoryTests {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static class MainBean {
|
||||||
|
|
||||||
|
@InnerValid
|
||||||
|
private InnerBean inner = new InnerBean();
|
||||||
|
|
||||||
|
public InnerBean getInner() {
|
||||||
|
return inner;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InnerBean {
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
public String getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
public void setValue(String value) {
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
|
@Target(ElementType.FIELD)
|
||||||
|
@Constraint(validatedBy=InnerValidator.class)
|
||||||
|
public static @interface InnerValid {
|
||||||
|
String message() default "NOT VALID";
|
||||||
|
Class<?>[] groups() default { };
|
||||||
|
Class<? extends Payload>[] payload() default {};
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class InnerValidator implements ConstraintValidator<InnerValid, InnerBean> {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void initialize(InnerValid constraintAnnotation) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isValid(InnerBean bean, ConstraintValidatorContext context) {
|
||||||
|
context.disableDefaultConstraintViolation();
|
||||||
|
if (bean.getValue() == null) {
|
||||||
|
context.buildConstraintViolationWithTemplate("NULL"). addNode("value").addConstraintViolation();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -25,7 +25,6 @@ import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ReflectionUtils;
|
import org.springframework.util.ReflectionUtils;
|
||||||
|
|
||||||
|
|
@ -145,7 +144,7 @@ public abstract class BridgeMethodResolver {
|
||||||
private static Method findGenericDeclaration(Method bridgeMethod) {
|
private static Method findGenericDeclaration(Method bridgeMethod) {
|
||||||
// Search parent types for method that has same signature as bridge.
|
// Search parent types for method that has same signature as bridge.
|
||||||
Class superclass = bridgeMethod.getDeclaringClass().getSuperclass();
|
Class superclass = bridgeMethod.getDeclaringClass().getSuperclass();
|
||||||
while (!Object.class.equals(superclass)) {
|
while (superclass != null && !Object.class.equals(superclass)) {
|
||||||
Method method = searchForMatch(superclass, bridgeMethod);
|
Method method = searchForMatch(superclass, bridgeMethod);
|
||||||
if (method != null && !method.isBridge()) {
|
if (method != null && !method.isBridge()) {
|
||||||
return method;
|
return method;
|
||||||
|
|
@ -219,8 +218,6 @@ public abstract class BridgeMethodResolver {
|
||||||
* @return whether signatures match as described
|
* @return whether signatures match as described
|
||||||
*/
|
*/
|
||||||
public static boolean isVisibilityBridgeMethodPair(Method bridgeMethod, Method bridgedMethod) {
|
public static boolean isVisibilityBridgeMethodPair(Method bridgeMethod, Method bridgedMethod) {
|
||||||
Assert.isTrue(bridgeMethod != null);
|
|
||||||
Assert.isTrue(bridgedMethod != null);
|
|
||||||
if (bridgeMethod == bridgedMethod) {
|
if (bridgeMethod == bridgedMethod) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -65,15 +65,15 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
|
|
||||||
|
|
||||||
public String[] getParameterNames(Method method) {
|
public String[] getParameterNames(Method method) {
|
||||||
Class<?> declaringClass = method.getDeclaringClass();
|
Method originalMethod = BridgeMethodResolver.findBridgedMethod(method);
|
||||||
|
Class<?> declaringClass = originalMethod.getDeclaringClass();
|
||||||
Map<Member, String[]> map = this.parameterNamesCache.get(declaringClass);
|
Map<Member, String[]> map = this.parameterNamesCache.get(declaringClass);
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
// initialize cache
|
|
||||||
map = inspectClass(declaringClass);
|
map = inspectClass(declaringClass);
|
||||||
this.parameterNamesCache.put(declaringClass, map);
|
this.parameterNamesCache.put(declaringClass, map);
|
||||||
}
|
}
|
||||||
if (map != NO_DEBUG_INFO_MAP) {
|
if (map != NO_DEBUG_INFO_MAP) {
|
||||||
return map.get(method);
|
return map.get(originalMethod);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -82,14 +82,12 @@ public class LocalVariableTableParameterNameDiscoverer implements ParameterNameD
|
||||||
Class<?> declaringClass = ctor.getDeclaringClass();
|
Class<?> declaringClass = ctor.getDeclaringClass();
|
||||||
Map<Member, String[]> map = this.parameterNamesCache.get(declaringClass);
|
Map<Member, String[]> map = this.parameterNamesCache.get(declaringClass);
|
||||||
if (map == null) {
|
if (map == null) {
|
||||||
// initialize cache
|
|
||||||
map = inspectClass(declaringClass);
|
map = inspectClass(declaringClass);
|
||||||
this.parameterNamesCache.put(declaringClass, map);
|
this.parameterNamesCache.put(declaringClass, map);
|
||||||
}
|
}
|
||||||
if (map != NO_DEBUG_INFO_MAP) {
|
if (map != NO_DEBUG_INFO_MAP) {
|
||||||
return map.get(ctor);
|
return map.get(ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,6 +16,10 @@
|
||||||
|
|
||||||
package org.springframework.core.annotation;
|
package org.springframework.core.annotation;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.springframework.core.OrderComparator;
|
import org.springframework.core.OrderComparator;
|
||||||
import org.springframework.core.Ordered;
|
import org.springframework.core.Ordered;
|
||||||
|
|
||||||
|
|
@ -37,7 +41,7 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
|
||||||
/**
|
/**
|
||||||
* Shared default instance of AnnotationAwareOrderComparator.
|
* Shared default instance of AnnotationAwareOrderComparator.
|
||||||
*/
|
*/
|
||||||
public static AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
|
public static final AnnotationAwareOrderComparator INSTANCE = new AnnotationAwareOrderComparator();
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -46,7 +50,8 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
|
||||||
return ((Ordered) obj).getOrder();
|
return ((Ordered) obj).getOrder();
|
||||||
}
|
}
|
||||||
if (obj != null) {
|
if (obj != null) {
|
||||||
Order order = obj.getClass().getAnnotation(Order.class);
|
Class<?> clazz = (obj instanceof Class ? (Class) obj : obj.getClass());
|
||||||
|
Order order = clazz.getAnnotation(Order.class);
|
||||||
if (order != null) {
|
if (order != null) {
|
||||||
return order.value();
|
return order.value();
|
||||||
}
|
}
|
||||||
|
|
@ -54,4 +59,31 @@ public class AnnotationAwareOrderComparator extends OrderComparator {
|
||||||
return Ordered.LOWEST_PRECEDENCE;
|
return Ordered.LOWEST_PRECEDENCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the given List with a default AnnotationAwareOrderComparator.
|
||||||
|
* <p>Optimized to skip sorting for lists with size 0 or 1,
|
||||||
|
* in order to avoid unnecessary array extraction.
|
||||||
|
* @param list the List to sort
|
||||||
|
* @see java.util.Collections#sort(java.util.List, java.util.Comparator)
|
||||||
|
*/
|
||||||
|
public static void sort(List<?> list) {
|
||||||
|
if (list.size() > 1) {
|
||||||
|
Collections.sort(list, INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort the given array with a default AnnotationAwareOrderComparator.
|
||||||
|
* <p>Optimized to skip sorting for lists with size 0 or 1,
|
||||||
|
* in order to avoid unnecessary array extraction.
|
||||||
|
* @param array the array to sort
|
||||||
|
* @see java.util.Arrays#sort(Object[], java.util.Comparator)
|
||||||
|
*/
|
||||||
|
public static void sort(Object[] array) {
|
||||||
|
if (array.length > 1) {
|
||||||
|
Arrays.sort(array, INSTANCE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -19,7 +19,7 @@ package org.springframework.core.annotation;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.AnnotatedElement;
|
import java.lang.reflect.AnnotatedElement;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
|
|
@ -255,8 +255,9 @@ public abstract class AnnotationUtils {
|
||||||
* declared locally on the supplied {@code clazz}. The supplied {@link Class}
|
* declared locally on the supplied {@code clazz}. The supplied {@link Class}
|
||||||
* may represent any type.
|
* may represent any type.
|
||||||
* <p>Note: This method does <strong>not</strong> determine if the annotation is
|
* <p>Note: This method does <strong>not</strong> determine if the annotation is
|
||||||
* {@link java.lang.annotation.Inherited inherited}. For greater clarity regarding inherited
|
* {@linkplain java.lang.annotation.Inherited inherited}. For greater clarity
|
||||||
* annotations, consider using {@link #isAnnotationInherited(Class, Class)} instead.
|
* regarding inherited annotations, consider using
|
||||||
|
* {@link #isAnnotationInherited(Class, Class)} instead.
|
||||||
* @param annotationType the Class object corresponding to the annotation type
|
* @param annotationType the Class object corresponding to the annotation type
|
||||||
* @param clazz the Class object corresponding to the class on which to check for the annotation
|
* @param clazz the Class object corresponding to the class on which to check for the annotation
|
||||||
* @return {@code true} if an annotation for the specified {@code annotationType}
|
* @return {@code true} if an annotation for the specified {@code annotationType}
|
||||||
|
|
@ -268,7 +269,7 @@ public abstract class AnnotationUtils {
|
||||||
Assert.notNull(annotationType, "Annotation type must not be null");
|
Assert.notNull(annotationType, "Annotation type must not be null");
|
||||||
Assert.notNull(clazz, "Class must not be null");
|
Assert.notNull(clazz, "Class must not be null");
|
||||||
boolean declaredLocally = false;
|
boolean declaredLocally = false;
|
||||||
for (Annotation annotation : Arrays.asList(clazz.getDeclaredAnnotations())) {
|
for (Annotation annotation : clazz.getDeclaredAnnotations()) {
|
||||||
if (annotation.annotationType().equals(annotationType)) {
|
if (annotation.annotationType().equals(annotationType)) {
|
||||||
declaredLocally = true;
|
declaredLocally = true;
|
||||||
break;
|
break;
|
||||||
|
|
@ -279,16 +280,16 @@ public abstract class AnnotationUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine whether an annotation for the specified {@code annotationType} is present
|
* Determine whether an annotation for the specified {@code annotationType} is present
|
||||||
* on the supplied {@code clazz} and is {@link java.lang.annotation.Inherited inherited}
|
* on the supplied {@code clazz} and is {@linkplain java.lang.annotation.Inherited inherited}
|
||||||
* i.e., not declared locally for the class).
|
* (i.e., not declared locally for the class).
|
||||||
* <p>If the supplied {@code clazz} is an interface, only the interface itself will be checked.
|
* <p>If the supplied {@code clazz} is an interface, only the interface itself will be checked.
|
||||||
* In accordance with standard meta-annotation semantics, the inheritance hierarchy for interfaces
|
* In accordance with standard meta-annotation semantics, the inheritance hierarchy for interfaces
|
||||||
* will not be traversed. See the {@link java.lang.annotation.Inherited JavaDoc} for the
|
* will not be traversed. See the {@linkplain java.lang.annotation.Inherited Javadoc} for the
|
||||||
* @Inherited meta-annotation for further details regarding annotation inheritance.
|
* {@code @Inherited} meta-annotation for further details regarding annotation inheritance.
|
||||||
* @param annotationType the Class object corresponding to the annotation type
|
* @param annotationType the Class object corresponding to the annotation type
|
||||||
* @param clazz the Class object corresponding to the class on which to check for the annotation
|
* @param clazz the Class object corresponding to the class on which to check for the annotation
|
||||||
* @return {@code true} if an annotation for the specified {@code annotationType} is present
|
* @return {@code true} if an annotation for the specified {@code annotationType} is present
|
||||||
* on the supplied {@code clazz} and is {@link java.lang.annotation.Inherited inherited}
|
* on the supplied {@code clazz} and is <em>inherited</em>
|
||||||
* @see Class#isAnnotationPresent(Class)
|
* @see Class#isAnnotationPresent(Class)
|
||||||
* @see #isAnnotationDeclaredLocally(Class, Class)
|
* @see #isAnnotationDeclaredLocally(Class, Class)
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
package org.springframework.core.convert;
|
package org.springframework.core.convert;
|
||||||
|
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.lang.reflect.Array;
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
|
@ -33,6 +34,8 @@ import org.springframework.util.ObjectUtils;
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author Phillip Webb
|
||||||
|
* @author Sam Brannen
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class TypeDescriptor {
|
public class TypeDescriptor {
|
||||||
|
|
@ -75,7 +78,8 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor from a {@link MethodParameter}.
|
* Create a new type descriptor from a {@link MethodParameter}.
|
||||||
* Use this constructor when a source or target conversion point is a constructor parameter, method parameter, or method return value.
|
* <p>Use this constructor when a source or target conversion point is a
|
||||||
|
* constructor parameter, method parameter, or method return value.
|
||||||
* @param methodParameter the method parameter
|
* @param methodParameter the method parameter
|
||||||
*/
|
*/
|
||||||
public TypeDescriptor(MethodParameter methodParameter) {
|
public TypeDescriptor(MethodParameter methodParameter) {
|
||||||
|
|
@ -84,7 +88,7 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor from a {@link Field}.
|
* Create a new type descriptor from a {@link Field}.
|
||||||
* Use this constructor when source or target conversion point is a field.
|
* <p>Use this constructor when a source or target conversion point is a field.
|
||||||
* @param field the field
|
* @param field the field
|
||||||
*/
|
*/
|
||||||
public TypeDescriptor(Field field) {
|
public TypeDescriptor(Field field) {
|
||||||
|
|
@ -93,7 +97,8 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor from a {@link Property}.
|
* Create a new type descriptor from a {@link Property}.
|
||||||
* Use this constructor when a source or target conversion point is a property on a Java class.
|
* <p>Use this constructor when a source or target conversion point is a
|
||||||
|
* property on a Java class.
|
||||||
* @param property the property
|
* @param property the property
|
||||||
*/
|
*/
|
||||||
public TypeDescriptor(Property property) {
|
public TypeDescriptor(Property property) {
|
||||||
|
|
@ -103,8 +108,11 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor from the given type.
|
* Create a new type descriptor from the given type.
|
||||||
* Use this to instruct the conversion system to convert an object to a specific target type, when no type location such as a method parameter or field is available to provide additional conversion context.
|
* <p>Use this to instruct the conversion system to convert an object to a
|
||||||
* Generally prefer use of {@link #forObject(Object)} for constructing type descriptors from source objects, as it handles the null object case.
|
* specific target type, when no type location such as a method parameter or
|
||||||
|
* field is available to provide additional conversion context.
|
||||||
|
* <p>Generally prefer use of {@link #forObject(Object)} for constructing type
|
||||||
|
* descriptors from source objects, as it handles the {@code null} object case.
|
||||||
* @param type the class
|
* @param type the class
|
||||||
* @return the type descriptor
|
* @return the type descriptor
|
||||||
*/
|
*/
|
||||||
|
|
@ -114,12 +122,15 @@ public class TypeDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor from a java.util.Collection type.
|
* Create a new type descriptor from a {@link java.util.Collection} type.
|
||||||
* Useful for converting to typed Collections.
|
* <p>Useful for converting to typed Collections.
|
||||||
* For example, a List<String> could be converted to a List<EmailAddress> by converting to a targetType built with this method.
|
* <p>For example, a {@code List<String>} could be converted to a
|
||||||
* The method call to construct such a TypeDescriptor would look something like: collection(List.class, TypeDescriptor.valueOf(EmailAddress.class));
|
* {@code List<EmailAddress>} by converting to a targetType built with this method.
|
||||||
|
* The method call to construct such a {@code TypeDescriptor} would look something
|
||||||
|
* like: {@code collection(List.class, TypeDescriptor.valueOf(EmailAddress.class));}
|
||||||
* @param collectionType the collection type, which must implement {@link Collection}.
|
* @param collectionType the collection type, which must implement {@link Collection}.
|
||||||
* @param elementTypeDescriptor a descriptor for the collection's element type, used to convert collection elements
|
* @param elementTypeDescriptor a descriptor for the collection's element type,
|
||||||
|
* used to convert collection elements
|
||||||
* @return the collection type descriptor
|
* @return the collection type descriptor
|
||||||
*/
|
*/
|
||||||
public static TypeDescriptor collection(Class<?> collectionType, TypeDescriptor elementTypeDescriptor) {
|
public static TypeDescriptor collection(Class<?> collectionType, TypeDescriptor elementTypeDescriptor) {
|
||||||
|
|
@ -130,9 +141,9 @@ public class TypeDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor from a java.util.Map type.
|
* Create a new type descriptor from a {@link java.util.Map} type.
|
||||||
* Useful for Converting to typed Maps.
|
* <p>Useful for converting to typed Maps.
|
||||||
* For example, a Map<String, String> could be converted to a Map<Id, EmailAddress> by converting to a targetType built with this method:
|
* <p>For example, a Map<String, String> could be converted to a Map<Id, EmailAddress> by converting to a targetType built with this method:
|
||||||
* The method call to construct such a TypeDescriptor would look something like: map(Map.class, TypeDescriptor.valueOf(Id.class), TypeDescriptor.valueOf(EmailAddress.class));
|
* The method call to construct such a TypeDescriptor would look something like: map(Map.class, TypeDescriptor.valueOf(Id.class), TypeDescriptor.valueOf(EmailAddress.class));
|
||||||
* @param mapType the map type, which must implement {@link Map}
|
* @param mapType the map type, which must implement {@link Map}
|
||||||
* @param keyTypeDescriptor a descriptor for the map's key type, used to convert map keys
|
* @param keyTypeDescriptor a descriptor for the map's key type, used to convert map keys
|
||||||
|
|
@ -146,19 +157,44 @@ public class TypeDescriptor {
|
||||||
return new TypeDescriptor(mapType, keyTypeDescriptor, valueTypeDescriptor);
|
return new TypeDescriptor(mapType, keyTypeDescriptor, valueTypeDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new type descriptor as an array of the specified type.
|
||||||
|
* <p>For example to create a {@code Map<String,String>[]} use
|
||||||
|
* {@code TypeDescriptor.array(TypeDescriptor.map(Map.class, TypeDescriptor.value(String.class), TypeDescriptor.value(String.class)))}.
|
||||||
|
* @param elementTypeDescriptor the {@link TypeDescriptor} of the array element or {@code null}
|
||||||
|
* @return an array {@link TypeDescriptor} or {@code null} if {@code elementTypeDescriptor} is {@code null}
|
||||||
|
* @since 3.2.1
|
||||||
|
*/
|
||||||
|
public static TypeDescriptor array(TypeDescriptor elementTypeDescriptor) {
|
||||||
|
if(elementTypeDescriptor == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
Class<?> type = Array.newInstance(elementTypeDescriptor.getType(), 0).getClass();
|
||||||
|
return new TypeDescriptor(type, elementTypeDescriptor, null, null, elementTypeDescriptor.getAnnotations());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a type descriptor for a nested type declared within the method parameter.
|
* Creates a type descriptor for a nested type declared within the method parameter.
|
||||||
* For example, if the methodParameter is a List<String> and the nestingLevel is 1, the nested type descriptor will be String.class.
|
* <p>For example, if the methodParameter is a {@code List<String>} and the
|
||||||
* If the methodParameter is a List<List<String>> and the nestingLevel is 2, the nested type descriptor will also be a String.class.
|
* nesting level is 1, the nested type descriptor will be String.class.
|
||||||
* If the methodParameter is a Map<Integer, String> and the nesting level is 1, the nested type descriptor will be String, derived from the map value.
|
* <p>If the methodParameter is a {@code List<List<String>>} and the nesting
|
||||||
* If the methodParameter is a List<Map<Integer, String>> and the nesting level is 2, the nested type descriptor will be String, derived from the map value.
|
* level is 2, the nested type descriptor will also be a String.class.
|
||||||
* Returns null if a nested type cannot be obtained because it was not declared.
|
* <p>If the methodParameter is a {@code Map<Integer, String>} and the nesting
|
||||||
* For example, if the method parameter is a List<?>, the nested type descriptor returned will be <tt>null</tt>.
|
* level is 1, the nested type descriptor will be String, derived from the map value.
|
||||||
|
* <p>If the methodParameter is a {@code List<Map<Integer, String>>} and the
|
||||||
|
* nesting level is 2, the nested type descriptor will be String, derived from the map value.
|
||||||
|
* <p>Returns {@code null} if a nested type cannot be obtained because it was not declared.
|
||||||
|
* For example, if the method parameter is a {@code List<?>}, the nested type
|
||||||
|
* descriptor returned will be {@code null}.
|
||||||
* @param methodParameter the method parameter with a nestingLevel of 1
|
* @param methodParameter the method parameter with a nestingLevel of 1
|
||||||
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the method parameter
|
* @param nestingLevel the nesting level of the collection/array element or
|
||||||
* @return the nested type descriptor at the specified nesting level, or null if it could not be obtained
|
* map key/value declaration within the method parameter
|
||||||
* @throws IllegalArgumentException if the nesting level of the input {@link MethodParameter} argument is not 1
|
* @return the nested type descriptor at the specified nesting level, or null
|
||||||
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types
|
* if it could not be obtained
|
||||||
|
* @throws IllegalArgumentException if the nesting level of the input
|
||||||
|
* {@link MethodParameter} argument is not 1
|
||||||
|
* @throws IllegalArgumentException if the types up to the specified nesting
|
||||||
|
* level are not of collection, array, or map types
|
||||||
*/
|
*/
|
||||||
public static TypeDescriptor nested(MethodParameter methodParameter, int nestingLevel) {
|
public static TypeDescriptor nested(MethodParameter methodParameter, int nestingLevel) {
|
||||||
if (methodParameter.getNestingLevel() != 1) {
|
if (methodParameter.getNestingLevel() != 1) {
|
||||||
|
|
@ -169,16 +205,23 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a type descriptor for a nested type declared within the field.
|
* Creates a type descriptor for a nested type declared within the field.
|
||||||
* <p>For example, if the field is a {@code List<String>} and the nestingLevel is 1, the nested type descriptor will be {@code String.class}.
|
* <p>For example, if the field is a {@code List<String>} and the nesting
|
||||||
* If the field is a {@code List<List<String>>} and the nestingLevel is 2, the nested type descriptor will also be a {@code String.class}.
|
* level is 1, the nested type descriptor will be {@code String.class}.
|
||||||
* If the field is a {@code Map<Integer, String>} and the nestingLevel is 1, the nested type descriptor will be String, derived from the map value.
|
* <p>If the field is a {@code List<List<String>>} and the nesting level is
|
||||||
* If the field is a {@code List<Map<Integer, String>>} and the nestingLevel is 2, the nested type descriptor will be String, derived from the map value.
|
* 2, the nested type descriptor will also be a {@code String.class}.
|
||||||
* Returns {@code null} if a nested type cannot be obtained because it was not declared.
|
* <p>If the field is a {@code Map<Integer, String>} and the nesting level
|
||||||
* For example, if the field is a {@code List<?>}, the nested type descriptor returned will be {@code null}.
|
* is 1, the nested type descriptor will be String, derived from the map value.
|
||||||
|
* <p>If the field is a {@code List<Map<Integer, String>>} and the nesting
|
||||||
|
* level is 2, the nested type descriptor will be String, derived from the map value.
|
||||||
|
* <p>Returns {@code null} if a nested type cannot be obtained because it was not declared.
|
||||||
|
* For example, if the field is a {@code List<?>}, the nested type descriptor returned will be {@code null}.
|
||||||
* @param field the field
|
* @param field the field
|
||||||
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the field
|
* @param nestingLevel the nesting level of the collection/array element or
|
||||||
* @return the nested type descriptor at the specified nestingLevel, or null if it could not be obtained
|
* map key/value declaration within the field
|
||||||
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types
|
* @return the nested type descriptor at the specified nesting level, or null
|
||||||
|
* if it could not be obtained
|
||||||
|
* @throws IllegalArgumentException if the types up to the specified nesting
|
||||||
|
* level are not of collection, array, or map types
|
||||||
*/
|
*/
|
||||||
public static TypeDescriptor nested(Field field, int nestingLevel) {
|
public static TypeDescriptor nested(Field field, int nestingLevel) {
|
||||||
return nested(new FieldDescriptor(field), nestingLevel);
|
return nested(new FieldDescriptor(field), nestingLevel);
|
||||||
|
|
@ -186,16 +229,24 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a type descriptor for a nested type declared within the property.
|
* Creates a type descriptor for a nested type declared within the property.
|
||||||
* <p>For example, if the property is a {@code List<String>} and the nestingLevel is 1, the nested type descriptor will be {@code String.class}.
|
* <p>For example, if the property is a {@code List<String>} and the nesting
|
||||||
* If the property is a {@code List<List<String>>} and the nestingLevel is 2, the nested type descriptor will also be a {@code String.class}.
|
* level is 1, the nested type descriptor will be {@code String.class}.
|
||||||
* If the property is a {@code Map<Integer, String>} and the nestingLevel is 1, the nested type descriptor will be String, derived from the map value.
|
* <p>If the property is a {@code List<List<String>>} and the nesting level
|
||||||
* If the property is a {@code List<Map<Integer, String>>} and the nestingLevel is 2, the nested type descriptor will be String, derived from the map value.
|
* is 2, the nested type descriptor will also be a {@code String.class}.
|
||||||
* Returns {@code null} if a nested type cannot be obtained because it was not declared.
|
* <p>If the property is a {@code Map<Integer, String>} and the nesting level
|
||||||
* For example, if the property is a {@code List<?>}, the nested type descriptor returned will be {@code null}.
|
* is 1, the nested type descriptor will be String, derived from the map value.
|
||||||
|
* <p>If the property is a {@code List<Map<Integer, String>>} and the nesting
|
||||||
|
* level is 2, the nested type descriptor will be String, derived from the map value.
|
||||||
|
* <p>Returns {@code null} if a nested type cannot be obtained because it was not declared.
|
||||||
|
* For example, if the property is a {@code List<?>}, the nested type descriptor
|
||||||
|
* returned will be {@code null}.
|
||||||
* @param property the property
|
* @param property the property
|
||||||
* @param nestingLevel the nesting level of the collection/array element or map key/value declaration within the property
|
* @param nestingLevel the nesting level of the collection/array element or
|
||||||
* @return the nested type descriptor at the specified nestingLevel, or {@code null} if it could not be obtained
|
* map key/value declaration within the property
|
||||||
* @throws IllegalArgumentException if the types up to the specified nesting level are not of collection, array, or map types
|
* @return the nested type descriptor at the specified nesting level, or
|
||||||
|
* {@code null} if it could not be obtained
|
||||||
|
* @throws IllegalArgumentException if the types up to the specified nesting
|
||||||
|
* level are not of collection, array, or map types
|
||||||
*/
|
*/
|
||||||
public static TypeDescriptor nested(Property property, int nestingLevel) {
|
public static TypeDescriptor nested(Property property, int nestingLevel) {
|
||||||
return nested(new BeanPropertyDescriptor(property), nestingLevel);
|
return nested(new BeanPropertyDescriptor(property), nestingLevel);
|
||||||
|
|
@ -203,8 +254,8 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor for an object.
|
* Create a new type descriptor for an object.
|
||||||
* Use this factory method to introspect a source object before asking the conversion system to convert it to some another type.
|
* <p>Use this factory method to introspect a source object before asking the conversion system to convert it to some another type.
|
||||||
* If the provided object is null, returns null, else calls {@link #valueOf(Class)} to build a TypeDescriptor from the object's class.
|
* <p>If the provided object is null, returns null, else calls {@link #valueOf(Class)} to build a TypeDescriptor from the object's class.
|
||||||
* @param source the source object
|
* @param source the source object
|
||||||
* @return the type descriptor
|
* @return the type descriptor
|
||||||
*/
|
*/
|
||||||
|
|
@ -214,7 +265,7 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of the backing class, method parameter, field, or property described by this TypeDescriptor.
|
* The type of the backing class, method parameter, field, or property described by this TypeDescriptor.
|
||||||
* Returns primitive types as-is.
|
* <p>Returns primitive types as-is.
|
||||||
* <p>See {@link #getObjectType()} for a variation of this operation that resolves primitive types
|
* <p>See {@link #getObjectType()} for a variation of this operation that resolves primitive types
|
||||||
* to their corresponding Object types if necessary.
|
* to their corresponding Object types if necessary.
|
||||||
* @return the type, or {@code null}
|
* @return the type, or {@code null}
|
||||||
|
|
@ -235,7 +286,7 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Narrows this {@link TypeDescriptor} by setting its type to the class of the provided value.
|
* Narrows this {@link TypeDescriptor} by setting its type to the class of the provided value.
|
||||||
* If the value is {@code null}, no narrowing is performed and this TypeDescriptor is returned unchanged.
|
* <p>If the value is {@code null}, no narrowing is performed and this TypeDescriptor is returned unchanged.
|
||||||
* <p>Designed to be called by binding frameworks when they read property, field, or method return values.
|
* <p>Designed to be called by binding frameworks when they read property, field, or method return values.
|
||||||
* Allows such frameworks to narrow a TypeDescriptor built from a declared property, field, or method return value type.
|
* Allows such frameworks to narrow a TypeDescriptor built from a declared property, field, or method return value type.
|
||||||
* For example, a field declared as {@code java.lang.Object} would be narrowed to {@code java.util.HashMap}
|
* For example, a field declared as {@code java.lang.Object} would be narrowed to {@code java.util.HashMap}
|
||||||
|
|
@ -255,7 +306,6 @@ public class TypeDescriptor {
|
||||||
/**
|
/**
|
||||||
* Cast this {@link TypeDescriptor} to a superclass or implemented interface
|
* Cast this {@link TypeDescriptor} to a superclass or implemented interface
|
||||||
* preserving annotations and nested type context.
|
* preserving annotations and nested type context.
|
||||||
*
|
|
||||||
* @param superType the super type to cast to (can be {@code null}
|
* @param superType the super type to cast to (can be {@code null}
|
||||||
* @return a new TypeDescriptor for the up-cast type
|
* @return a new TypeDescriptor for the up-cast type
|
||||||
* @throws IllegalArgumentException if this type is not assignable to the super-type
|
* @throws IllegalArgumentException if this type is not assignable to the super-type
|
||||||
|
|
@ -324,7 +374,7 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if an object of this type descriptor can be assigned to the location described by the given type descriptor.
|
* Returns true if an object of this type descriptor can be assigned to the location described by the given type descriptor.
|
||||||
* For example, valueOf(String.class).isAssignableTo(valueOf(CharSequence.class)) returns true because a String value can be assigned to a CharSequence variable.
|
* <p>For example, valueOf(String.class).isAssignableTo(valueOf(CharSequence.class)) returns true because a String value can be assigned to a CharSequence variable.
|
||||||
* On the other hand, valueOf(Number.class).isAssignableTo(valueOf(Integer.class)) returns false because, while all Integers are Numbers, not all Numbers are Integers.
|
* On the other hand, valueOf(Number.class).isAssignableTo(valueOf(Integer.class)) returns false because, while all Integers are Numbers, not all Numbers are Integers.
|
||||||
* <p>
|
* <p>
|
||||||
* For arrays, collections, and maps, element and key/value types are checked if declared.
|
* For arrays, collections, and maps, element and key/value types are checked if declared.
|
||||||
|
|
@ -382,10 +432,10 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this type is a {@link Collection} or an Array, creates a element TypeDescriptor from the provided collection or array element.
|
* If this type is a {@link Collection} or an Array, creates a element TypeDescriptor from the provided collection or array element.
|
||||||
* Narrows the {@link #getElementTypeDescriptor() elementType} property to the class of the provided collection or array element.
|
* <p>Narrows the {@link #getElementTypeDescriptor() elementType} property to the class of the provided collection or array element.
|
||||||
* For example, if this describes a java.util.List<java.lang.Number< and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
* For example, if this describes a java.util.List<java.lang.Number< and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||||
* If this describes a java.util.List<?> and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
* If this describes a java.util.List<?> and the element argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
||||||
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
* <p>Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
||||||
* @param element the collection or array element
|
* @param element the collection or array element
|
||||||
* @return a element type descriptor, narrowed to the type of the provided element
|
* @return a element type descriptor, narrowed to the type of the provided element
|
||||||
* @throws IllegalStateException if this type is not a java.util.Collection or Array type
|
* @throws IllegalStateException if this type is not a java.util.Collection or Array type
|
||||||
|
|
@ -417,10 +467,10 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this type is a {@link Map}, creates a mapKey {@link TypeDescriptor} from the provided map key.
|
* If this type is a {@link Map}, creates a mapKey {@link TypeDescriptor} from the provided map key.
|
||||||
* Narrows the {@link #getMapKeyTypeDescriptor() mapKeyType} property to the class of the provided map key.
|
* <p>Narrows the {@link #getMapKeyTypeDescriptor() mapKeyType} property to the class of the provided map key.
|
||||||
* For example, if this describes a java.util.Map<java.lang.Number, java.lang.String< and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
* For example, if this describes a java.util.Map<java.lang.Number, java.lang.String< and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||||
* If this describes a java.util.Map<?, ?> and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
* <p>If this describes a java.util.Map<?, ?> and the key argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
||||||
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
* <p>Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
||||||
* @param mapKey the map key
|
* @param mapKey the map key
|
||||||
* @return the map key type descriptor
|
* @return the map key type descriptor
|
||||||
* @throws IllegalStateException if this type is not a java.util.Map
|
* @throws IllegalStateException if this type is not a java.util.Map
|
||||||
|
|
@ -432,7 +482,7 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this type is a {@link Map} and its value type is parameterized, returns the map's value type.
|
* If this type is a {@link Map} and its value type is parameterized, returns the map's value type.
|
||||||
* If the Map's value type is not parameterized, returns null indicating the value type is not declared.
|
* <p>If the Map's value type is not parameterized, returns null indicating the value type is not declared.
|
||||||
* @return the Map value type, or {@code null} if this type is a Map but its value type is not parameterized
|
* @return the Map value type, or {@code null} if this type is a Map but its value type is not parameterized
|
||||||
* @throws IllegalStateException if this type is not a java.util.Map
|
* @throws IllegalStateException if this type is not a java.util.Map
|
||||||
*/
|
*/
|
||||||
|
|
@ -443,10 +493,10 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If this type is a {@link Map}, creates a mapValue {@link TypeDescriptor} from the provided map value.
|
* If this type is a {@link Map}, creates a mapValue {@link TypeDescriptor} from the provided map value.
|
||||||
* Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property to the class of the provided map value.
|
* <p>Narrows the {@link #getMapValueTypeDescriptor() mapValueType} property to the class of the provided map value.
|
||||||
* For example, if this describes a java.util.Map<java.lang.String, java.lang.Number< and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
* For example, if this describes a java.util.Map<java.lang.String, java.lang.Number< and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer.
|
||||||
* If this describes a java.util.Map<?, ?> and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
* If this describes a java.util.Map<?, ?> and the value argument is a java.lang.Integer, the returned TypeDescriptor will be java.lang.Integer as well.
|
||||||
* Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
* <p>Annotation and nested type context will be preserved in the narrowed TypeDescriptor that is returned.
|
||||||
* @param mapValue the map value
|
* @param mapValue the map value
|
||||||
* @return the map value type descriptor
|
* @return the map value type descriptor
|
||||||
* @throws IllegalStateException if this type is not a java.util.Map
|
* @throws IllegalStateException if this type is not a java.util.Map
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -31,13 +31,12 @@ import java.util.Properties;
|
||||||
*
|
*
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see org.springframework.mock.env.MockPropertySource
|
|
||||||
*/
|
*/
|
||||||
public class PropertiesPropertySource extends MapPropertySource {
|
public class PropertiesPropertySource extends MapPropertySource {
|
||||||
|
|
||||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public PropertiesPropertySource(String name, Properties source) {
|
public PropertiesPropertySource(String name, Properties source) {
|
||||||
super(name, (Map)source);
|
super(name, (Map) source);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,17 +17,21 @@
|
||||||
package org.springframework.core.env;
|
package org.springframework.core.env;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read-only {@code Map<String, String>} implementation that is backed by system properties or environment
|
* Read-only {@code Map<String, String>} implementation that is backed by system
|
||||||
* variables.
|
* properties or environment variables.
|
||||||
*
|
*
|
||||||
* <p>Used by {@link AbstractApplicationContext} when a {@link SecurityManager} prohibits access to {@link
|
* <p>Used by {@link AbstractApplicationContext} when a {@link SecurityManager} prohibits
|
||||||
* System#getProperties()} or {@link System#getenv()}.
|
* access to {@link System#getProperties()} or {@link System#getenv()}. It is for this
|
||||||
|
* reason that the implementations of {@link #keySet()}, {@link #entrySet()}, and
|
||||||
|
* {@link #values()} always return empty even though {@link #get(Object)} may in fact
|
||||||
|
* return non-null if the current security manager allows access to individual keys.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
|
@ -85,7 +89,7 @@ abstract class ReadOnlySystemAttributesMap implements Map<String, String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<String> keySet() {
|
public Set<String> keySet() {
|
||||||
throw new UnsupportedOperationException();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void putAll(Map<? extends String, ? extends String> m) {
|
public void putAll(Map<? extends String, ? extends String> m) {
|
||||||
|
|
@ -93,11 +97,11 @@ abstract class ReadOnlySystemAttributesMap implements Map<String, String> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Collection<String> values() {
|
public Collection<String> values() {
|
||||||
throw new UnsupportedOperationException();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Entry<String, String>> entrySet() {
|
public Set<Entry<String, String>> entrySet() {
|
||||||
throw new UnsupportedOperationException();
|
return Collections.emptySet();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -76,7 +76,7 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean containsProperty(String name) {
|
public boolean containsProperty(String name) {
|
||||||
return resolvePropertyName(name) != null;
|
return getProperty(name) != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -102,8 +102,8 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check to see if this property source contains a property with the given name, or
|
* Check to see if this property source contains a property with the given name, or
|
||||||
* any underscore / uppercase variation thereof. Return the resolved name or
|
* any underscore / uppercase variation thereof. Return the resolved name if one is
|
||||||
* {@code null} if none found.
|
* found or otherwise the original name. Never returns {@code null}.
|
||||||
*/
|
*/
|
||||||
private String resolvePropertyName(String name) {
|
private String resolvePropertyName(String name) {
|
||||||
if (super.containsProperty(name)) {
|
if (super.containsProperty(name)) {
|
||||||
|
|
@ -127,6 +127,6 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -205,18 +205,14 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||||
*/
|
*/
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
StringBuilder builder = new StringBuilder("class path resource [");
|
StringBuilder builder = new StringBuilder("class path resource [");
|
||||||
|
|
||||||
String pathToUse = path;
|
String pathToUse = path;
|
||||||
|
|
||||||
if (this.clazz != null && !pathToUse.startsWith("/")) {
|
if (this.clazz != null && !pathToUse.startsWith("/")) {
|
||||||
builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
|
builder.append(ClassUtils.classPackageAsResourcePath(this.clazz));
|
||||||
builder.append('/');
|
builder.append('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathToUse.startsWith("/")) {
|
if (pathToUse.startsWith("/")) {
|
||||||
pathToUse = pathToUse.substring(1);
|
pathToUse = pathToUse.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.append(pathToUse);
|
builder.append(pathToUse);
|
||||||
builder.append(']');
|
builder.append(']');
|
||||||
return builder.toString();
|
return builder.toString();
|
||||||
|
|
@ -232,9 +228,9 @@ public class ClassPathResource extends AbstractFileResolvingResource {
|
||||||
}
|
}
|
||||||
if (obj instanceof ClassPathResource) {
|
if (obj instanceof ClassPathResource) {
|
||||||
ClassPathResource otherRes = (ClassPathResource) obj;
|
ClassPathResource otherRes = (ClassPathResource) obj;
|
||||||
return (this.path.equals(otherRes.path)
|
return (this.path.equals(otherRes.path) &&
|
||||||
&& ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) && ObjectUtils.nullSafeEquals(
|
ObjectUtils.nullSafeEquals(this.classLoader, otherRes.classLoader) &&
|
||||||
this.clazz, otherRes.clazz));
|
ObjectUtils.nullSafeEquals(this.clazz, otherRes.clazz));
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,8 +17,10 @@
|
||||||
package org.springframework.core.io.support;
|
package org.springframework.core.io.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.Reader;
|
import java.io.Reader;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
@ -39,7 +41,9 @@ public class EncodedResource {
|
||||||
|
|
||||||
private final Resource resource;
|
private final Resource resource;
|
||||||
|
|
||||||
private final String encoding;
|
private String encoding;
|
||||||
|
|
||||||
|
private Charset charset;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -48,7 +52,8 @@ public class EncodedResource {
|
||||||
* @param resource the Resource to hold
|
* @param resource the Resource to hold
|
||||||
*/
|
*/
|
||||||
public EncodedResource(Resource resource) {
|
public EncodedResource(Resource resource) {
|
||||||
this(resource, null);
|
Assert.notNull(resource, "Resource must not be null");
|
||||||
|
this.resource = resource;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -63,6 +68,18 @@ public class EncodedResource {
|
||||||
this.encoding = encoding;
|
this.encoding = encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new EncodedResource for the given Resource,
|
||||||
|
* using the specified encoding.
|
||||||
|
* @param resource the Resource to hold
|
||||||
|
* @param charset the charset to use for reading from the resource
|
||||||
|
*/
|
||||||
|
public EncodedResource(Resource resource, Charset charset) {
|
||||||
|
Assert.notNull(resource, "Resource must not be null");
|
||||||
|
this.resource = resource;
|
||||||
|
this.charset = charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the Resource held.
|
* Return the Resource held.
|
||||||
|
|
@ -79,13 +96,36 @@ public class EncodedResource {
|
||||||
return this.encoding;
|
return this.encoding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the charset to use for reading from the resource,
|
||||||
|
* or {@code null} if none specified.
|
||||||
|
*/
|
||||||
|
public final Charset getCharset() {
|
||||||
|
return this.charset;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether a {@link Reader} is required as opposed to an {@link InputStream},
|
||||||
|
* i.e. whether an encoding or a charset has been specified.
|
||||||
|
* @see #getReader()
|
||||||
|
* @see #getInputStream()
|
||||||
|
*/
|
||||||
|
public boolean requiresReader() {
|
||||||
|
return (this.encoding != null || this.charset != null);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open a {@code java.io.Reader} for the specified resource,
|
* Open a {@code java.io.Reader} for the specified resource,
|
||||||
* using the specified encoding (if any).
|
* using the specified encoding (if any).
|
||||||
* @throws IOException if opening the Reader failed
|
* @throws IOException if opening the Reader failed
|
||||||
|
* @see #requiresReader()
|
||||||
*/
|
*/
|
||||||
public Reader getReader() throws IOException {
|
public Reader getReader() throws IOException {
|
||||||
if (this.encoding != null) {
|
if (this.charset != null) {
|
||||||
|
return new InputStreamReader(this.resource.getInputStream(), this.charset);
|
||||||
|
}
|
||||||
|
else if (this.encoding != null) {
|
||||||
return new InputStreamReader(this.resource.getInputStream(), this.encoding);
|
return new InputStreamReader(this.resource.getInputStream(), this.encoding);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -93,6 +133,16 @@ public class EncodedResource {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Open an {@code java.io.InputStream} for the specified resource,
|
||||||
|
* typically assuming that there is no specific encoding to use.
|
||||||
|
* @throws IOException if opening the InputStream failed
|
||||||
|
* @see #requiresReader()
|
||||||
|
*/
|
||||||
|
public InputStream getInputStream() throws IOException {
|
||||||
|
return this.resource.getInputStream();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,8 +17,6 @@
|
||||||
package org.springframework.core.io.support;
|
package org.springframework.core.io.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
|
|
@ -39,9 +37,6 @@ import org.springframework.util.PropertiesPersister;
|
||||||
*/
|
*/
|
||||||
public abstract class PropertiesLoaderSupport {
|
public abstract class PropertiesLoaderSupport {
|
||||||
|
|
||||||
public static final String XML_FILE_EXTENSION = ".xml";
|
|
||||||
|
|
||||||
|
|
||||||
/** Logger available to subclasses */
|
/** Logger available to subclasses */
|
||||||
protected final Log logger = LogFactory.getLog(getClass());
|
protected final Log logger = LogFactory.getLog(getClass());
|
||||||
|
|
||||||
|
|
@ -167,7 +162,7 @@ public abstract class PropertiesLoaderSupport {
|
||||||
/**
|
/**
|
||||||
* Load properties into the given instance.
|
* Load properties into the given instance.
|
||||||
* @param props the Properties instance to load into
|
* @param props the Properties instance to load into
|
||||||
* @throws java.io.IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
* @see #setLocations
|
* @see #setLocations
|
||||||
*/
|
*/
|
||||||
protected void loadProperties(Properties props) throws IOException {
|
protected void loadProperties(Properties props) throws IOException {
|
||||||
|
|
@ -176,21 +171,9 @@ public abstract class PropertiesLoaderSupport {
|
||||||
if (logger.isInfoEnabled()) {
|
if (logger.isInfoEnabled()) {
|
||||||
logger.info("Loading properties file from " + location);
|
logger.info("Loading properties file from " + location);
|
||||||
}
|
}
|
||||||
InputStream is = null;
|
|
||||||
try {
|
try {
|
||||||
is = location.getInputStream();
|
PropertiesLoaderUtils.fillProperties(
|
||||||
String filename = location.getFilename();
|
props, new EncodedResource(location, this.fileEncoding), this.propertiesPersister);
|
||||||
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
|
|
||||||
this.propertiesPersister.loadFromXml(props, is);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (this.fileEncoding != null) {
|
|
||||||
this.propertiesPersister.load(props, new InputStreamReader(is, this.fileEncoding));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
this.propertiesPersister.load(props, is);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (IOException ex) {
|
catch (IOException ex) {
|
||||||
if (this.ignoreResourceNotFound) {
|
if (this.ignoreResourceNotFound) {
|
||||||
|
|
@ -202,11 +185,6 @@ public abstract class PropertiesLoaderSupport {
|
||||||
throw ex;
|
throw ex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
finally {
|
|
||||||
if (is != null) {
|
|
||||||
is.close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -18,6 +18,7 @@ package org.springframework.core.io.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.Reader;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.net.URLConnection;
|
import java.net.URLConnection;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
|
@ -26,6 +27,8 @@ import java.util.Properties;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
|
import org.springframework.util.DefaultPropertiesPersister;
|
||||||
|
import org.springframework.util.PropertiesPersister;
|
||||||
import org.springframework.util.ResourceUtils;
|
import org.springframework.util.ResourceUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -42,11 +45,76 @@ import org.springframework.util.ResourceUtils;
|
||||||
*/
|
*/
|
||||||
public abstract class PropertiesLoaderUtils {
|
public abstract class PropertiesLoaderUtils {
|
||||||
|
|
||||||
|
private static final String XML_FILE_EXTENSION = ".xml";
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load properties from the given resource.
|
* Load properties from the given EncodedResource,
|
||||||
|
* potentially defining a specific encoding for the properties file.
|
||||||
|
* @see #fillProperties(java.util.Properties, EncodedResource)
|
||||||
|
*/
|
||||||
|
public static Properties loadProperties(EncodedResource resource) throws IOException {
|
||||||
|
Properties props = new Properties();
|
||||||
|
fillProperties(props, resource);
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fill the given properties from the given EncodedResource,
|
||||||
|
* potentially defining a specific encoding for the properties file.
|
||||||
|
* @param props the Properties instance to load into
|
||||||
|
* @param resource the resource to load from
|
||||||
|
* @throws IOException in case of I/O errors
|
||||||
|
*/
|
||||||
|
public static void fillProperties(Properties props, EncodedResource resource)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
fillProperties(props, resource, new DefaultPropertiesPersister());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Actually load properties from the given EncodedResource into the given Properties instance.
|
||||||
|
* @param props the Properties instance to load into
|
||||||
|
* @param resource the resource to load from
|
||||||
|
* @param persister the PropertiesPersister to use
|
||||||
|
* @throws IOException in case of I/O errors
|
||||||
|
*/
|
||||||
|
static void fillProperties(Properties props, EncodedResource resource, PropertiesPersister persister)
|
||||||
|
throws IOException {
|
||||||
|
|
||||||
|
InputStream stream = null;
|
||||||
|
Reader reader = null;
|
||||||
|
try {
|
||||||
|
String filename = resource.getResource().getFilename();
|
||||||
|
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
|
||||||
|
stream = resource.getInputStream();
|
||||||
|
persister.loadFromXml(props, stream);
|
||||||
|
}
|
||||||
|
else if (resource.requiresReader()) {
|
||||||
|
reader = resource.getReader();
|
||||||
|
persister.load(props, reader);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
stream = resource.getInputStream();
|
||||||
|
persister.load(props, stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
if (stream != null) {
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
if (reader != null) {
|
||||||
|
reader.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Load properties from the given resource (in ISO-8859-1 encoding).
|
||||||
* @param resource the resource to load from
|
* @param resource the resource to load from
|
||||||
* @return the populated Properties instance
|
* @return the populated Properties instance
|
||||||
* @throws IOException if loading failed
|
* @throws IOException if loading failed
|
||||||
|
* @see #fillProperties(java.util.Properties, Resource)
|
||||||
*/
|
*/
|
||||||
public static Properties loadProperties(Resource resource) throws IOException {
|
public static Properties loadProperties(Resource resource) throws IOException {
|
||||||
Properties props = new Properties();
|
Properties props = new Properties();
|
||||||
|
|
@ -55,7 +123,7 @@ public abstract class PropertiesLoaderUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fill the given properties from the given resource.
|
* Fill the given properties from the given resource (in ISO-8859-1 encoding).
|
||||||
* @param props the Properties instance to fill
|
* @param props the Properties instance to fill
|
||||||
* @param resource the resource to load from
|
* @param resource the resource to load from
|
||||||
* @throws IOException if loading failed
|
* @throws IOException if loading failed
|
||||||
|
|
@ -63,7 +131,13 @@ public abstract class PropertiesLoaderUtils {
|
||||||
public static void fillProperties(Properties props, Resource resource) throws IOException {
|
public static void fillProperties(Properties props, Resource resource) throws IOException {
|
||||||
InputStream is = resource.getInputStream();
|
InputStream is = resource.getInputStream();
|
||||||
try {
|
try {
|
||||||
props.load(is);
|
String filename = resource.getFilename();
|
||||||
|
if (filename != null && filename.endsWith(XML_FILE_EXTENSION)) {
|
||||||
|
props.loadFromXML(is);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
props.load(is);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
finally {
|
finally {
|
||||||
is.close();
|
is.close();
|
||||||
|
|
@ -71,8 +145,8 @@ public abstract class PropertiesLoaderUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load all properties from the given class path resource,
|
* Load all properties from the specified class path resource
|
||||||
* using the default class loader.
|
* (in ISO-8859-1 encoding), using the default class loader.
|
||||||
* <p>Merges properties if more than one resource of the same name
|
* <p>Merges properties if more than one resource of the same name
|
||||||
* found in the class path.
|
* found in the class path.
|
||||||
* @param resourceName the name of the class path resource
|
* @param resourceName the name of the class path resource
|
||||||
|
|
@ -84,8 +158,8 @@ public abstract class PropertiesLoaderUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Load all properties from the given class path resource,
|
* Load all properties from the specified class path resource
|
||||||
* using the given class loader.
|
* (in ISO-8859-1 encoding), using the given class loader.
|
||||||
* <p>Merges properties if more than one resource of the same name
|
* <p>Merges properties if more than one resource of the same name
|
||||||
* found in the class path.
|
* found in the class path.
|
||||||
* @param resourceName the name of the class path resource
|
* @param resourceName the name of the class path resource
|
||||||
|
|
@ -100,24 +174,26 @@ public abstract class PropertiesLoaderUtils {
|
||||||
if (clToUse == null) {
|
if (clToUse == null) {
|
||||||
clToUse = ClassUtils.getDefaultClassLoader();
|
clToUse = ClassUtils.getDefaultClassLoader();
|
||||||
}
|
}
|
||||||
Properties properties = new Properties();
|
Properties props = new Properties();
|
||||||
Enumeration urls = clToUse.getResources(resourceName);
|
Enumeration urls = clToUse.getResources(resourceName);
|
||||||
while (urls.hasMoreElements()) {
|
while (urls.hasMoreElements()) {
|
||||||
URL url = (URL) urls.nextElement();
|
URL url = (URL) urls.nextElement();
|
||||||
InputStream is = null;
|
URLConnection con = url.openConnection();
|
||||||
|
ResourceUtils.useCachesIfNecessary(con);
|
||||||
|
InputStream is = con.getInputStream();
|
||||||
try {
|
try {
|
||||||
URLConnection con = url.openConnection();
|
if (resourceName != null && resourceName.endsWith(XML_FILE_EXTENSION)) {
|
||||||
ResourceUtils.useCachesIfNecessary(con);
|
props.loadFromXML(is);
|
||||||
is = con.getInputStream();
|
}
|
||||||
properties.load(is);
|
else {
|
||||||
}
|
props.load(is);
|
||||||
finally {
|
|
||||||
if (is != null) {
|
|
||||||
is.close();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
finally {
|
||||||
|
is.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return properties;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -17,30 +17,51 @@
|
||||||
package org.springframework.core.io.support;
|
package org.springframework.core.io.support;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.springframework.core.env.PropertiesPropertySource;
|
import org.springframework.core.env.PropertiesPropertySource;
|
||||||
|
import org.springframework.core.io.DefaultResourceLoader;
|
||||||
import org.springframework.core.io.Resource;
|
import org.springframework.core.io.Resource;
|
||||||
import org.springframework.util.ClassUtils;
|
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Subclass of {@link PropertiesPropertySource} that loads a {@link Properties}
|
* Subclass of {@link PropertiesPropertySource} that loads a {@link Properties}
|
||||||
* object from a given {@link org.springframework.core.io.Resource} or resource location such as
|
* object from a given {@link org.springframework.core.io.Resource} or resource location such as
|
||||||
* {@code "classpath:/com/myco/foo.properties"} or {@code "file:/path/to/file.properties"}.
|
* {@code "classpath:/com/myco/foo.properties"} or {@code "file:/path/to/file.xml"}.
|
||||||
|
* Both traditional and XML-based properties file formats are supported, however in order
|
||||||
|
* for XML processing to take effect, the underlying {@code Resource}'s
|
||||||
|
* {@link org.springframework.core.io.Resource#getFilename() getFilename()} method must
|
||||||
|
* return non-{@code null} and end in ".xml".
|
||||||
*
|
*
|
||||||
* @author Chris Beams
|
* @author Chris Beams
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public class ResourcePropertySource extends PropertiesPropertySource {
|
public class ResourcePropertySource extends PropertiesPropertySource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a PropertySource having the given name based on Properties
|
* Create a PropertySource having the given name based on Properties
|
||||||
* loaded from the given resource.
|
* loaded from the given encoded resource.
|
||||||
|
*/
|
||||||
|
public ResourcePropertySource(String name, EncodedResource resource) throws IOException {
|
||||||
|
super(name, PropertiesLoaderUtils.loadProperties(resource));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PropertySource based on Properties loaded from the given resource.
|
||||||
|
* The name of the PropertySource will be generated based on the
|
||||||
|
* {@link Resource#getDescription() description} of the given resource.
|
||||||
|
*/
|
||||||
|
public ResourcePropertySource(EncodedResource resource) throws IOException {
|
||||||
|
this(getNameForResource(resource.getResource()), resource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PropertySource having the given name based on Properties
|
||||||
|
* loaded from the given encoded resource.
|
||||||
*/
|
*/
|
||||||
public ResourcePropertySource(String name, Resource resource) throws IOException {
|
public ResourcePropertySource(String name, Resource resource) throws IOException {
|
||||||
super(name, loadPropertiesForResource(resource));
|
super(name, PropertiesLoaderUtils.loadProperties(new EncodedResource(resource)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -58,17 +79,7 @@ public class ResourcePropertySource extends PropertiesPropertySource {
|
||||||
* resource (assuming it is prefixed with {@code classpath:}).
|
* resource (assuming it is prefixed with {@code classpath:}).
|
||||||
*/
|
*/
|
||||||
public ResourcePropertySource(String name, String location, ClassLoader classLoader) throws IOException {
|
public ResourcePropertySource(String name, String location, ClassLoader classLoader) throws IOException {
|
||||||
this(name, getResourceForLocation(location, classLoader));
|
this(name, new DefaultResourceLoader(classLoader).getResource(location));
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create a PropertySource having the given name based on Properties loaded from
|
|
||||||
* the given resource location. The default thread context class loader will be
|
|
||||||
* used to load the resource (assuming the location string is prefixed with
|
|
||||||
* {@code classpath:}.
|
|
||||||
*/
|
|
||||||
public ResourcePropertySource(String name, String location) throws IOException {
|
|
||||||
this(name, location, ClassUtils.getDefaultClassLoader());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -79,7 +90,17 @@ public class ResourcePropertySource extends PropertiesPropertySource {
|
||||||
* resource.
|
* resource.
|
||||||
*/
|
*/
|
||||||
public ResourcePropertySource(String location, ClassLoader classLoader) throws IOException {
|
public ResourcePropertySource(String location, ClassLoader classLoader) throws IOException {
|
||||||
this(getResourceForLocation(location, classLoader));
|
this(new DefaultResourceLoader(classLoader).getResource(location));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a PropertySource having the given name based on Properties loaded from
|
||||||
|
* the given resource location. The default thread context class loader will be
|
||||||
|
* used to load the resource (assuming the location string is prefixed with
|
||||||
|
* {@code classpath:}.
|
||||||
|
*/
|
||||||
|
public ResourcePropertySource(String name, String location) throws IOException {
|
||||||
|
this(name, new DefaultResourceLoader().getResource(location));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -88,28 +109,12 @@ public class ResourcePropertySource extends PropertiesPropertySource {
|
||||||
* {@link Resource#getDescription() description} of the resource.
|
* {@link Resource#getDescription() description} of the resource.
|
||||||
*/
|
*/
|
||||||
public ResourcePropertySource(String location) throws IOException {
|
public ResourcePropertySource(String location) throws IOException {
|
||||||
this(getResourceForLocation(location, ClassUtils.getDefaultClassLoader()));
|
this(new DefaultResourceLoader().getResource(location));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private static Resource getResourceForLocation(String location, ClassLoader classLoader) {
|
|
||||||
return new PathMatchingResourcePatternResolver(classLoader).getResource(location);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static Properties loadPropertiesForResource(Resource resource) throws IOException {
|
|
||||||
Properties props = new Properties();
|
|
||||||
InputStream is = resource.getInputStream();
|
|
||||||
props.load(is);
|
|
||||||
try {
|
|
||||||
is.close();
|
|
||||||
} catch (IOException ex) {
|
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
return props;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the description string for the resource, and if empty returns
|
* Return the description string for the resource, and if empty returns
|
||||||
* the class name of the resource plus its identity hash code.
|
* the class name of the resource plus its identity hash code.
|
||||||
*/
|
*/
|
||||||
private static String getNameForResource(Resource resource) {
|
private static String getNameForResource(Resource resource) {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -60,12 +60,18 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
private final Map<String, AntPathStringMatcher> stringMatcherCache =
|
private final Map<String, AntPathStringMatcher> stringMatcherCache =
|
||||||
new ConcurrentHashMap<String, AntPathStringMatcher>(256);
|
new ConcurrentHashMap<String, AntPathStringMatcher>(256);
|
||||||
|
|
||||||
|
private boolean trimTokens = true;
|
||||||
|
|
||||||
|
|
||||||
/** Set the path separator to use for pattern parsing. Default is "/", as in Ant. */
|
/** Set the path separator to use for pattern parsing. Default is "/", as in Ant. */
|
||||||
public void setPathSeparator(String pathSeparator) {
|
public void setPathSeparator(String pathSeparator) {
|
||||||
this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
|
this.pathSeparator = (pathSeparator != null ? pathSeparator : DEFAULT_PATH_SEPARATOR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Whether to trim tokenized paths and patterns. */
|
||||||
|
public void setTrimTokens(boolean trimTokens) {
|
||||||
|
this.trimTokens = trimTokens;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isPattern(String path) {
|
public boolean isPattern(String path) {
|
||||||
return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
|
return (path.indexOf('*') != -1 || path.indexOf('?') != -1);
|
||||||
|
|
@ -95,8 +101,8 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
|
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, this.trimTokens, true);
|
||||||
String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator);
|
String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);
|
||||||
|
|
||||||
int pattIdxStart = 0;
|
int pattIdxStart = 0;
|
||||||
int pattIdxEnd = pattDirs.length - 1;
|
int pattIdxEnd = pattDirs.length - 1;
|
||||||
|
|
@ -246,8 +252,8 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
* does <strong>not</strong> enforce this.
|
* does <strong>not</strong> enforce this.
|
||||||
*/
|
*/
|
||||||
public String extractPathWithinPattern(String pattern, String path) {
|
public String extractPathWithinPattern(String pattern, String path) {
|
||||||
String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator);
|
String[] patternParts = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, this.trimTokens, true);
|
||||||
String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator);
|
String[] pathParts = StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -33,8 +33,8 @@ import java.util.Properties;
|
||||||
*
|
*
|
||||||
* <p>Allows for reading from any Reader and writing to any Writer, for example
|
* <p>Allows for reading from any Reader and writing to any Writer, for example
|
||||||
* to specify a charset for a properties file. This is a capability that standard
|
* to specify a charset for a properties file. This is a capability that standard
|
||||||
* {@code java.util.Properties} unfortunately lacks up until JDK 1.5:
|
* {@code java.util.Properties} unfortunately lacked up until JDK 1.5:
|
||||||
* You can only load files using the ISO-8859-1 charset there.
|
* You were only able to load files using the ISO-8859-1 charset there.
|
||||||
*
|
*
|
||||||
* <p>Loading from and storing to a stream delegates to {@code Properties.load}
|
* <p>Loading from and storing to a stream delegates to {@code Properties.load}
|
||||||
* and {@code Properties.store}, respectively, to be fully compatible with
|
* and {@code Properties.store}, respectively, to be fully compatible with
|
||||||
|
|
@ -49,20 +49,11 @@ import java.util.Properties;
|
||||||
* an encoding for a Reader/Writer (like ReloadableResourceBundleMessageSource's
|
* an encoding for a Reader/Writer (like ReloadableResourceBundleMessageSource's
|
||||||
* "defaultEncoding" and "fileEncodings" properties).
|
* "defaultEncoding" and "fileEncodings" properties).
|
||||||
*
|
*
|
||||||
* <p>As of Spring 1.2.2, this implementation also supports properties XML files,
|
|
||||||
* through the {@code loadFromXml} and {@code storeToXml} methods.
|
|
||||||
* The default implementations delegate to JDK 1.5's corresponding methods,
|
|
||||||
* throwing an exception if running on an older JDK. Those implementations
|
|
||||||
* could be subclassed to apply custom XML handling on JDK 1.4, for example.
|
|
||||||
*
|
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @since 10.03.2004
|
* @since 10.03.2004
|
||||||
* @see java.util.Properties
|
* @see java.util.Properties
|
||||||
* @see java.util.Properties#load
|
* @see java.util.Properties#load
|
||||||
* @see java.util.Properties#store
|
* @see java.util.Properties#store
|
||||||
* @see org.springframework.context.support.ReloadableResourceBundleMessageSource#setPropertiesPersister
|
|
||||||
* @see org.springframework.context.support.ReloadableResourceBundleMessageSource#setDefaultEncoding
|
|
||||||
* @see org.springframework.context.support.ReloadableResourceBundleMessageSource#setFileEncodings
|
|
||||||
*/
|
*/
|
||||||
public class DefaultPropertiesPersister implements PropertiesPersister {
|
public class DefaultPropertiesPersister implements PropertiesPersister {
|
||||||
|
|
||||||
|
|
@ -228,30 +219,15 @@ public class DefaultPropertiesPersister implements PropertiesPersister {
|
||||||
|
|
||||||
|
|
||||||
public void loadFromXml(Properties props, InputStream is) throws IOException {
|
public void loadFromXml(Properties props, InputStream is) throws IOException {
|
||||||
try {
|
props.loadFromXML(is);
|
||||||
props.loadFromXML(is);
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodError err) {
|
|
||||||
throw new IOException("Cannot load properties XML file - not running on JDK 1.5+: " + err.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeToXml(Properties props, OutputStream os, String header) throws IOException {
|
public void storeToXml(Properties props, OutputStream os, String header) throws IOException {
|
||||||
try {
|
props.storeToXML(os, header);
|
||||||
props.storeToXML(os, header);
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodError err) {
|
|
||||||
throw new IOException("Cannot store properties XML file - not running on JDK 1.5+: " + err.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void storeToXml(Properties props, OutputStream os, String header, String encoding) throws IOException {
|
public void storeToXml(Properties props, OutputStream os, String header, String encoding) throws IOException {
|
||||||
try {
|
props.storeToXML(os, header, encoding);
|
||||||
props.storeToXML(os, header, encoding);
|
|
||||||
}
|
|
||||||
catch (NoSuchMethodError err) {
|
|
||||||
throw new IOException("Cannot store properties XML file - not running on JDK 1.5+: " + err.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -13,16 +13,19 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.core.annotation;
|
package org.springframework.core.annotation;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.*;
|
import static org.hamcrest.CoreMatchers.*;
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link AnnotationAwareOrderComparator}.
|
* @author Juergen Hoeller
|
||||||
*
|
|
||||||
* @author Oliver Gierke
|
* @author Oliver Gierke
|
||||||
*/
|
*/
|
||||||
public class AnnotationAwareOrderComparatorTests {
|
public class AnnotationAwareOrderComparatorTests {
|
||||||
|
|
@ -31,4 +34,34 @@ public class AnnotationAwareOrderComparatorTests {
|
||||||
public void instanceVariableIsAnAnnotationAwareOrderComparator() {
|
public void instanceVariableIsAnAnnotationAwareOrderComparator() {
|
||||||
assertThat(AnnotationAwareOrderComparator.INSTANCE, is(instanceOf(AnnotationAwareOrderComparator.class)));
|
assertThat(AnnotationAwareOrderComparator.INSTANCE, is(instanceOf(AnnotationAwareOrderComparator.class)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sortInstances() {
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
list.add(new B());
|
||||||
|
list.add(new A());
|
||||||
|
AnnotationAwareOrderComparator.sort(list);
|
||||||
|
assertTrue(list.get(0) instanceof A);
|
||||||
|
assertTrue(list.get(1) instanceof B);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void sortClasses() {
|
||||||
|
List<Object> list = new ArrayList<>();
|
||||||
|
list.add(B.class);
|
||||||
|
list.add(A.class);
|
||||||
|
AnnotationAwareOrderComparator.sort(list);
|
||||||
|
assertEquals(A.class, list.get(0));
|
||||||
|
assertEquals(B.class, list.get(1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Order(1)
|
||||||
|
private static class A {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Order(2)
|
||||||
|
private static class B {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -25,6 +25,7 @@ import java.util.Collection;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
|
@ -36,6 +37,7 @@ import static org.junit.Assert.*;
|
||||||
/**
|
/**
|
||||||
* @author Keith Donald
|
* @author Keith Donald
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Phillip Webb
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("rawtypes")
|
@SuppressWarnings("rawtypes")
|
||||||
public class TypeDescriptorTests {
|
public class TypeDescriptorTests {
|
||||||
|
|
@ -849,4 +851,23 @@ public class TypeDescriptorTests {
|
||||||
assertEquals(TypeDescriptor.forObject(new CustomMap()).getMapValueTypeDescriptor(), TypeDescriptor.valueOf(Integer.class));
|
assertEquals(TypeDescriptor.forObject(new CustomMap()).getMapValueTypeDescriptor(), TypeDescriptor.valueOf(Integer.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createMapArray() throws Exception {
|
||||||
|
TypeDescriptor mapType = TypeDescriptor.map(LinkedHashMap.class, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(Integer.class));
|
||||||
|
TypeDescriptor arrayType = TypeDescriptor.array(mapType);
|
||||||
|
assertEquals(arrayType.getType(), LinkedHashMap[].class);
|
||||||
|
assertEquals(arrayType.getElementTypeDescriptor(), mapType);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createStringArray() throws Exception {
|
||||||
|
TypeDescriptor arrayType = TypeDescriptor.array(TypeDescriptor.valueOf(String.class));
|
||||||
|
assertEquals(arrayType, TypeDescriptor.valueOf(String[].class));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void createNullArray() throws Exception {
|
||||||
|
assertNull(TypeDescriptor.array(null));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -16,7 +16,14 @@
|
||||||
|
|
||||||
package org.springframework.core.convert.support;
|
package org.springframework.core.convert.support;
|
||||||
|
|
||||||
import static org.junit.Assert.*;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
import static org.junit.Assert.assertArrayEquals;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
import static org.junit.Assert.assertThat;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
|
||||||
import java.awt.Color;
|
import java.awt.Color;
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
|
|
@ -773,6 +780,30 @@ public class DefaultConversionTests {
|
||||||
assertEquals(new Long(1), e.getId());
|
assertEquals(new Long(1), e.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void convertCharArrayToString() throws Exception {
|
||||||
|
String converted = conversionService.convert(new char[] { 'a', 'b', 'c' }, String.class);
|
||||||
|
assertThat(converted, equalTo("a,b,c"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void convertStringToCharArray() throws Exception {
|
||||||
|
char[] converted = conversionService.convert("a,b,c", char[].class);
|
||||||
|
assertThat(converted, equalTo(new char[] { 'a', 'b', 'c' }));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void convertStringToCustomCharArray() throws Exception {
|
||||||
|
conversionService.addConverter(new Converter<String, char[]>() {
|
||||||
|
@Override
|
||||||
|
public char[] convert(String source) {
|
||||||
|
return source.toCharArray();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
char[] converted = conversionService.convert("abc", char[].class);
|
||||||
|
assertThat(converted, equalTo(new char[] { 'a', 'b', 'c' }));
|
||||||
|
}
|
||||||
|
|
||||||
public static class TestEntity {
|
public static class TestEntity {
|
||||||
|
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
|
||||||
75
spring-core/src/test/java/org/springframework/core/env/DummyEnvironment.java
vendored
Normal file
75
spring-core/src/test/java/org/springframework/core/env/DummyEnvironment.java
vendored
Normal file
|
|
@ -0,0 +1,75 @@
|
||||||
|
/*
|
||||||
|
* 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.core.env;
|
||||||
|
|
||||||
|
public class DummyEnvironment implements Environment {
|
||||||
|
|
||||||
|
public boolean containsProperty(String key) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty(String key) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getProperty(String key, String defaultValue) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getProperty(String key, Class<T> targetType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getProperty(String key, Class<T> targetType, T defaultValue) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> Class<T> getPropertyAsClass(String key, Class<T> targetType) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getRequiredProperty(String key) throws IllegalStateException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T getRequiredProperty(String key, Class<T> targetType)
|
||||||
|
throws IllegalStateException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String resolvePlaceholders(String text) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String resolveRequiredPlaceholders(String text)
|
||||||
|
throws IllegalArgumentException {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getActiveProfiles() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getDefaultProfiles() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean acceptsProfiles(String... profiles) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2013 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -456,7 +456,7 @@ public class StandardEnvironmentTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private static Map<String, String> getModifiableSystemEnvironment() {
|
public static Map<String, String> getModifiableSystemEnvironment() {
|
||||||
// for os x / linux
|
// for os x / linux
|
||||||
Class<?>[] classes = Collections.class.getDeclaredClasses();
|
Class<?>[] classes = Collections.class.getDeclaredClasses();
|
||||||
Map<String, String> env = System.getenv();
|
Map<String, String> env = System.getenv();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
|
||||||
|
<properties version="1.0">
|
||||||
|
<entry key="foo">bar</entry>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -39,6 +39,10 @@ public class ResourcePropertySourceTests {
|
||||||
private static final String PROPERTIES_LOCATION = "classpath:" + PROPERTIES_PATH;
|
private static final String PROPERTIES_LOCATION = "classpath:" + PROPERTIES_PATH;
|
||||||
private static final String PROPERTIES_RESOURCE_DESCRIPTION = "class path resource [" + PROPERTIES_PATH + "]";
|
private static final String PROPERTIES_RESOURCE_DESCRIPTION = "class path resource [" + PROPERTIES_PATH + "]";
|
||||||
|
|
||||||
|
private static final String XML_PROPERTIES_PATH = "org/springframework/core/io/example.xml";
|
||||||
|
private static final String XML_PROPERTIES_LOCATION = "classpath:" + XML_PROPERTIES_PATH;
|
||||||
|
private static final String XML_PROPERTIES_RESOURCE_DESCRIPTION = "class path resource [" + XML_PROPERTIES_PATH + "]";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void withLocationAndGeneratedName() throws IOException {
|
public void withLocationAndGeneratedName() throws IOException {
|
||||||
PropertySource<?> ps = new ResourcePropertySource(PROPERTIES_LOCATION);
|
PropertySource<?> ps = new ResourcePropertySource(PROPERTIES_LOCATION);
|
||||||
|
|
@ -46,6 +50,13 @@ public class ResourcePropertySourceTests {
|
||||||
assertThat(ps.getName(), is(PROPERTIES_RESOURCE_DESCRIPTION));
|
assertThat(ps.getName(), is(PROPERTIES_RESOURCE_DESCRIPTION));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void xmlWithLocationAndGeneratedName() throws IOException {
|
||||||
|
PropertySource<?> ps = new ResourcePropertySource(XML_PROPERTIES_LOCATION);
|
||||||
|
assertEquals(ps.getProperty("foo"), "bar");
|
||||||
|
assertThat(ps.getName(), is(XML_PROPERTIES_RESOURCE_DESCRIPTION));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void withLocationAndExplicitName() throws IOException {
|
public void withLocationAndExplicitName() throws IOException {
|
||||||
PropertySource<?> ps = new ResourcePropertySource("ps1", PROPERTIES_LOCATION);
|
PropertySource<?> ps = new ResourcePropertySource("ps1", PROPERTIES_LOCATION);
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -542,6 +542,14 @@ public class AntPathMatcherTests {
|
||||||
paths.clear();
|
paths.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SPR-8687
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void trimTokensOff() {
|
||||||
|
pathMatcher.setTrimTokens(false);
|
||||||
|
|
||||||
|
assertTrue(pathMatcher.match("/group/{groupName}/members", "/group/sales/members"));
|
||||||
|
assertTrue(pathMatcher.match("/group/{groupName}/members", "/group/ sales/members"));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,15 +16,6 @@
|
||||||
|
|
||||||
package org.springframework.util;
|
package org.springframework.util;
|
||||||
|
|
||||||
import static org.hamcrest.CoreMatchers.is;
|
|
||||||
import static org.junit.Assert.assertEquals;
|
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertNull;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
import static org.junit.Assert.fail;
|
|
||||||
|
|
||||||
import java.lang.reflect.Field;
|
import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
|
@ -33,10 +24,18 @@ import java.rmi.RemoteException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.hamcrest.Matchers;
|
||||||
|
|
||||||
import org.junit.Ignore;
|
import org.junit.Ignore;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.tests.Assume;
|
||||||
|
import org.springframework.tests.TestGroup;
|
||||||
import org.springframework.tests.sample.objects.TestObject;
|
import org.springframework.tests.sample.objects.TestObject;
|
||||||
|
|
||||||
|
import static org.hamcrest.CoreMatchers.is;
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
|
@ -347,6 +346,43 @@ public class ReflectionUtilsTests {
|
||||||
assertFalse(ObjectUtils.containsElement(methods, Parent.class.getMethod("m1")));
|
assertFalse(ObjectUtils.containsElement(methods, Parent.class.getMethod("m1")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getUniqueDeclaredMethods_isFastEnough() {
|
||||||
|
Assume.group(TestGroup.PERFORMANCE);
|
||||||
|
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
class C {
|
||||||
|
void m00() { } void m01() { } void m02() { } void m03() { } void m04() { }
|
||||||
|
void m05() { } void m06() { } void m07() { } void m08() { } void m09() { }
|
||||||
|
void m10() { } void m11() { } void m12() { } void m13() { } void m14() { }
|
||||||
|
void m15() { } void m16() { } void m17() { } void m18() { } void m19() { }
|
||||||
|
void m20() { } void m21() { } void m22() { } void m23() { } void m24() { }
|
||||||
|
void m25() { } void m26() { } void m27() { } void m28() { } void m29() { }
|
||||||
|
void m30() { } void m31() { } void m32() { } void m33() { } void m34() { }
|
||||||
|
void m35() { } void m36() { } void m37() { } void m38() { } void m39() { }
|
||||||
|
void m40() { } void m41() { } void m42() { } void m43() { } void m44() { }
|
||||||
|
void m45() { } void m46() { } void m47() { } void m48() { } void m49() { }
|
||||||
|
void m50() { } void m51() { } void m52() { } void m53() { } void m54() { }
|
||||||
|
void m55() { } void m56() { } void m57() { } void m58() { } void m59() { }
|
||||||
|
void m60() { } void m61() { } void m62() { } void m63() { } void m64() { }
|
||||||
|
void m65() { } void m66() { } void m67() { } void m68() { } void m69() { }
|
||||||
|
void m70() { } void m71() { } void m72() { } void m73() { } void m74() { }
|
||||||
|
void m75() { } void m76() { } void m77() { } void m78() { } void m79() { }
|
||||||
|
void m80() { } void m81() { } void m82() { } void m83() { } void m84() { }
|
||||||
|
void m85() { } void m86() { } void m87() { } void m88() { } void m89() { }
|
||||||
|
void m90() { } void m91() { } void m92() { } void m93() { } void m94() { }
|
||||||
|
void m95() { } void m96() { } void m97() { } void m98() { } void m99() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
StopWatch sw = new StopWatch();
|
||||||
|
sw.start();
|
||||||
|
Method[] methods = ReflectionUtils.getUniqueDeclaredMethods(C.class);
|
||||||
|
sw.stop();
|
||||||
|
long totalMs = sw.getTotalTimeMillis();
|
||||||
|
assertThat(methods.length, Matchers.greaterThan(100));
|
||||||
|
assertThat(totalMs, Matchers.lessThan(10L));
|
||||||
|
}
|
||||||
|
|
||||||
private static class ListSavingMethodCallback implements ReflectionUtils.MethodCallback {
|
private static class ListSavingMethodCallback implements ReflectionUtils.MethodCallback {
|
||||||
|
|
||||||
private List<String> methodNames = new LinkedList<String>();
|
private List<String> methodNames = new LinkedList<String>();
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -108,7 +108,8 @@ public enum SpelMessage {
|
||||||
OPERAND_NOT_INCREMENTABLE(Kind.ERROR,1066,"the expression component ''{0}'' does not support increment"), //
|
OPERAND_NOT_INCREMENTABLE(Kind.ERROR,1066,"the expression component ''{0}'' does not support increment"), //
|
||||||
OPERAND_NOT_DECREMENTABLE(Kind.ERROR,1067,"the expression component ''{0}'' does not support decrement"), //
|
OPERAND_NOT_DECREMENTABLE(Kind.ERROR,1067,"the expression component ''{0}'' does not support decrement"), //
|
||||||
NOT_ASSIGNABLE(Kind.ERROR,1068,"the expression component ''{0}'' is not assignable"), //
|
NOT_ASSIGNABLE(Kind.ERROR,1068,"the expression component ''{0}'' is not assignable"), //
|
||||||
;
|
MISSING_CHARACTER(Kind.ERROR,1069,"missing expected character ''{0}''"),
|
||||||
|
LEFT_OPERAND_PROBLEM(Kind.ERROR,1070, "Problem parsing left operand");
|
||||||
|
|
||||||
private Kind kind;
|
private Kind kind;
|
||||||
private int code;
|
private int code;
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -37,6 +37,7 @@ import org.springframework.util.StringUtils;
|
||||||
* Hand written SpEL parser. Instances are reusable but are not thread safe.
|
* Hand written SpEL parser. Instances are reusable but are not thread safe.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Phillip Webb
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||||
|
|
@ -104,8 +105,8 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||||
Token t = peekToken();
|
Token t = peekToken();
|
||||||
if (t.kind==TokenKind.ASSIGN) { // a=b
|
if (t.kind==TokenKind.ASSIGN) { // a=b
|
||||||
if (expr==null) {
|
if (expr==null) {
|
||||||
expr = new NullLiteral(toPos(t.startpos-1,t.endpos-1));
|
expr = new NullLiteral(toPos(t.startpos-1,t.endpos-1));
|
||||||
}
|
}
|
||||||
nextToken();
|
nextToken();
|
||||||
SpelNodeImpl assignedValue = eatLogicalOrExpression();
|
SpelNodeImpl assignedValue = eatLogicalOrExpression();
|
||||||
return new Assign(toPos(t),expr,assignedValue);
|
return new Assign(toPos(t),expr,assignedValue);
|
||||||
|
|
@ -139,7 +140,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||||
while (peekIdentifierToken("or") || peekToken(TokenKind.SYMBOLIC_OR)) {
|
while (peekIdentifierToken("or") || peekToken(TokenKind.SYMBOLIC_OR)) {
|
||||||
Token t = nextToken(); //consume OR
|
Token t = nextToken(); //consume OR
|
||||||
SpelNodeImpl rhExpr = eatLogicalAndExpression();
|
SpelNodeImpl rhExpr = eatLogicalAndExpression();
|
||||||
checkRightOperand(t,rhExpr);
|
checkOperands(t,expr,rhExpr);
|
||||||
expr = new OpOr(toPos(t),expr,rhExpr);
|
expr = new OpOr(toPos(t),expr,rhExpr);
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
|
|
@ -151,7 +152,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||||
while (peekIdentifierToken("and") || peekToken(TokenKind.SYMBOLIC_AND)) {
|
while (peekIdentifierToken("and") || peekToken(TokenKind.SYMBOLIC_AND)) {
|
||||||
Token t = nextToken();// consume 'AND'
|
Token t = nextToken();// consume 'AND'
|
||||||
SpelNodeImpl rhExpr = eatRelationalExpression();
|
SpelNodeImpl rhExpr = eatRelationalExpression();
|
||||||
checkRightOperand(t,rhExpr);
|
checkOperands(t,expr,rhExpr);
|
||||||
expr = new OpAnd(toPos(t),expr,rhExpr);
|
expr = new OpAnd(toPos(t),expr,rhExpr);
|
||||||
}
|
}
|
||||||
return expr;
|
return expr;
|
||||||
|
|
@ -164,7 +165,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||||
if (relationalOperatorToken != null) {
|
if (relationalOperatorToken != null) {
|
||||||
Token t = nextToken(); //consume relational operator token
|
Token t = nextToken(); //consume relational operator token
|
||||||
SpelNodeImpl rhExpr = eatSumExpression();
|
SpelNodeImpl rhExpr = eatSumExpression();
|
||||||
checkRightOperand(t,rhExpr);
|
checkOperands(t,expr,rhExpr);
|
||||||
TokenKind tk = relationalOperatorToken.kind;
|
TokenKind tk = relationalOperatorToken.kind;
|
||||||
if (relationalOperatorToken.isNumericRelationalOperator()) {
|
if (relationalOperatorToken.isNumericRelationalOperator()) {
|
||||||
int pos = toPos(t);
|
int pos = toPos(t);
|
||||||
|
|
@ -217,7 +218,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||||
while (peekToken(TokenKind.STAR,TokenKind.DIV,TokenKind.MOD)) {
|
while (peekToken(TokenKind.STAR,TokenKind.DIV,TokenKind.MOD)) {
|
||||||
Token t = nextToken(); // consume STAR/DIV/MOD
|
Token t = nextToken(); // consume STAR/DIV/MOD
|
||||||
SpelNodeImpl rhExpr = eatPowerIncDecExpression();
|
SpelNodeImpl rhExpr = eatPowerIncDecExpression();
|
||||||
checkRightOperand(t,rhExpr);
|
checkOperands(t,expr,rhExpr);
|
||||||
if (t.kind==TokenKind.STAR) {
|
if (t.kind==TokenKind.STAR) {
|
||||||
expr = new OpMultiply(toPos(t),expr,rhExpr);
|
expr = new OpMultiply(toPos(t),expr,rhExpr);
|
||||||
} else if (t.kind==TokenKind.DIV) {
|
} else if (t.kind==TokenKind.DIV) {
|
||||||
|
|
@ -836,6 +837,17 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void checkOperands(Token token, SpelNodeImpl left, SpelNodeImpl right) {
|
||||||
|
checkLeftOperand(token, left);
|
||||||
|
checkRightOperand(token, right);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkLeftOperand(Token token, SpelNodeImpl operandExpression) {
|
||||||
|
if (operandExpression==null) {
|
||||||
|
raiseInternalException(token.startpos,SpelMessage.LEFT_OPERAND_PROBLEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void checkRightOperand(Token token, SpelNodeImpl operandExpression) {
|
private void checkRightOperand(Token token, SpelNodeImpl operandExpression) {
|
||||||
if (operandExpression==null) {
|
if (operandExpression==null) {
|
||||||
raiseInternalException(token.startpos,SpelMessage.RIGHT_OPERAND_PROBLEM);
|
raiseInternalException(token.startpos,SpelMessage.RIGHT_OPERAND_PROBLEM);
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -29,6 +29,7 @@ import org.springframework.util.Assert;
|
||||||
* Lex some input data into a stream of tokens that can then be parsed.
|
* Lex some input data into a stream of tokens that can then be parsed.
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
|
* @author Phillip Webb
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
class Tokenizer {
|
class Tokenizer {
|
||||||
|
|
@ -137,14 +138,20 @@ class Tokenizer {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '&':
|
case '&':
|
||||||
if (isTwoCharToken(TokenKind.SYMBOLIC_AND)) {
|
if (!isTwoCharToken(TokenKind.SYMBOLIC_AND)) {
|
||||||
pushPairToken(TokenKind.SYMBOLIC_AND);
|
throw new InternalParseException(new SpelParseException(
|
||||||
|
expressionString, pos,
|
||||||
|
SpelMessage.MISSING_CHARACTER, "&"));
|
||||||
}
|
}
|
||||||
|
pushPairToken(TokenKind.SYMBOLIC_AND);
|
||||||
break;
|
break;
|
||||||
case '|':
|
case '|':
|
||||||
if (isTwoCharToken(TokenKind.SYMBOLIC_OR)) {
|
if (!isTwoCharToken(TokenKind.SYMBOLIC_OR)) {
|
||||||
pushPairToken(TokenKind.SYMBOLIC_OR);
|
throw new InternalParseException(new SpelParseException(
|
||||||
|
expressionString, pos,
|
||||||
|
SpelMessage.MISSING_CHARACTER, "|"));
|
||||||
}
|
}
|
||||||
|
pushPairToken(TokenKind.SYMBOLIC_OR);
|
||||||
break;
|
break;
|
||||||
case '?':
|
case '?':
|
||||||
if (isTwoCharToken(TokenKind.SELECT)) {
|
if (isTwoCharToken(TokenKind.SELECT)) {
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -21,6 +21,8 @@ import java.lang.reflect.Field;
|
||||||
import java.lang.reflect.Member;
|
import java.lang.reflect.Member;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Modifier;
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
|
||||||
|
|
@ -42,6 +44,7 @@ import org.springframework.util.StringUtils;
|
||||||
*
|
*
|
||||||
* @author Andy Clement
|
* @author Andy Clement
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
|
* @author Phillip Webb
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public class ReflectivePropertyAccessor implements PropertyAccessor {
|
public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
|
|
@ -284,7 +287,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
|
|
||||||
private Method findGetterForProperty(String propertyName, Class<?> clazz, Object target) {
|
private Method findGetterForProperty(String propertyName, Class<?> clazz, Object target) {
|
||||||
Method method = findGetterForProperty(propertyName, clazz, target instanceof Class);
|
Method method = findGetterForProperty(propertyName, clazz, target instanceof Class);
|
||||||
if(method == null && target instanceof Class) {
|
if (method == null && target instanceof Class) {
|
||||||
method = findGetterForProperty(propertyName, target.getClass(), false);
|
method = findGetterForProperty(propertyName, target.getClass(), false);
|
||||||
}
|
}
|
||||||
return method;
|
return method;
|
||||||
|
|
@ -292,7 +295,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
|
|
||||||
private Method findSetterForProperty(String propertyName, Class<?> clazz, Object target) {
|
private Method findSetterForProperty(String propertyName, Class<?> clazz, Object target) {
|
||||||
Method method = findSetterForProperty(propertyName, clazz, target instanceof Class);
|
Method method = findSetterForProperty(propertyName, clazz, target instanceof Class);
|
||||||
if(method == null && target instanceof Class) {
|
if (method == null && target instanceof Class) {
|
||||||
method = findSetterForProperty(propertyName, target.getClass(), false);
|
method = findSetterForProperty(propertyName, target.getClass(), false);
|
||||||
}
|
}
|
||||||
return method;
|
return method;
|
||||||
|
|
@ -300,7 +303,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
|
|
||||||
private Field findField(String name, Class<?> clazz, Object target) {
|
private Field findField(String name, Class<?> clazz, Object target) {
|
||||||
Field field = findField(name, clazz, target instanceof Class);
|
Field field = findField(name, clazz, target instanceof Class);
|
||||||
if(field == null && target instanceof Class) {
|
if (field == null && target instanceof Class) {
|
||||||
field = findField(name, target.getClass(), false);
|
field = findField(name, target.getClass(), false);
|
||||||
}
|
}
|
||||||
return field;
|
return field;
|
||||||
|
|
@ -310,13 +313,13 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
* Find a getter method for the specified property.
|
* Find a getter method for the specified property.
|
||||||
*/
|
*/
|
||||||
protected Method findGetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
|
protected Method findGetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
|
||||||
Method[] ms = clazz.getMethods();
|
Method[] ms = getSortedClassMethods(clazz);
|
||||||
String propertyMethodSuffix = getPropertyMethodSuffix(propertyName);
|
String propertyMethodSuffix = getPropertyMethodSuffix(propertyName);
|
||||||
|
|
||||||
// Try "get*" method...
|
// Try "get*" method...
|
||||||
String getterName = "get" + propertyMethodSuffix;
|
String getterName = "get" + propertyMethodSuffix;
|
||||||
for (Method method : ms) {
|
for (Method method : ms) {
|
||||||
if (!method.isBridge() && method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
|
if (method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
|
||||||
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
@ -324,7 +327,7 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
// Try "is*" method...
|
// Try "is*" method...
|
||||||
getterName = "is" + propertyMethodSuffix;
|
getterName = "is" + propertyMethodSuffix;
|
||||||
for (Method method : ms) {
|
for (Method method : ms) {
|
||||||
if (!method.isBridge() && method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
|
if (method.getName().equals(getterName) && method.getParameterTypes().length == 0 &&
|
||||||
(boolean.class.equals(method.getReturnType()) || Boolean.class.equals(method.getReturnType())) &&
|
(boolean.class.equals(method.getReturnType()) || Boolean.class.equals(method.getReturnType())) &&
|
||||||
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
||||||
return method;
|
return method;
|
||||||
|
|
@ -337,10 +340,10 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
* Find a setter method for the specified property.
|
* Find a setter method for the specified property.
|
||||||
*/
|
*/
|
||||||
protected Method findSetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
|
protected Method findSetterForProperty(String propertyName, Class<?> clazz, boolean mustBeStatic) {
|
||||||
Method[] methods = clazz.getMethods();
|
Method[] methods = getSortedClassMethods(clazz);
|
||||||
String setterName = "set" + getPropertyMethodSuffix(propertyName);
|
String setterName = "set" + getPropertyMethodSuffix(propertyName);
|
||||||
for (Method method : methods) {
|
for (Method method : methods) {
|
||||||
if (!method.isBridge() && method.getName().equals(setterName) && method.getParameterTypes().length == 1 &&
|
if (method.getName().equals(setterName) && method.getParameterTypes().length == 1 &&
|
||||||
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
(!mustBeStatic || Modifier.isStatic(method.getModifiers()))) {
|
||||||
return method;
|
return method;
|
||||||
}
|
}
|
||||||
|
|
@ -348,6 +351,19 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns class methods ordered with non bridge methods appearing higher.
|
||||||
|
*/
|
||||||
|
private Method[] getSortedClassMethods(Class<?> clazz) {
|
||||||
|
Method[] methods = clazz.getMethods();
|
||||||
|
Arrays.sort(methods, new Comparator<Method>() {
|
||||||
|
public int compare(Method o1, Method o2) {
|
||||||
|
return (o1.isBridge() == o2.isBridge()) ? 0 : (o1.isBridge() ? 1 : -1);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return methods;
|
||||||
|
}
|
||||||
|
|
||||||
protected String getPropertyMethodSuffix(String propertyName) {
|
protected String getPropertyMethodSuffix(String propertyName) {
|
||||||
if (propertyName.length() > 1 && Character.isUpperCase(propertyName.charAt(1))) {
|
if (propertyName.length() > 1 && Character.isUpperCase(propertyName.charAt(1))) {
|
||||||
return propertyName;
|
return propertyName;
|
||||||
|
|
@ -367,6 +383,20 @@ public class ReflectivePropertyAccessor implements PropertyAccessor {
|
||||||
return field;
|
return field;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// We'll search superclasses and implemented interfaces explicitly,
|
||||||
|
// although it shouldn't be necessary - however, see SPR-10125.
|
||||||
|
if (clazz.getSuperclass() != null) {
|
||||||
|
Field field = findField(name, clazz.getSuperclass(), mustBeStatic);
|
||||||
|
if (field != null) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Class<?> implementedInterface : clazz.getInterfaces()) {
|
||||||
|
Field field = findField(name, implementedInterface, mustBeStatic);
|
||||||
|
if (field != null) {
|
||||||
|
return field;
|
||||||
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue