Convert CRLF (dos) to LF (unix)

Prior to this change, roughly 5% (~300 out of 6000+) of files under the
source tree had CRLF line endings as opposed to the majority which have
LF endings.

This change normalizes these files to LF for consistency going forward.

Command used:

$ git ls-files | xargs file | grep CRLF | cut -d":" -f1 | xargs dos2unix

Issue: SPR-5608
This commit is contained in:
Chris Beams
2011-12-21 14:42:42 +01:00
parent e1b645368a
commit 88913f2b23
293 changed files with 31091 additions and 31091 deletions

View File

@@ -1,41 +1,41 @@
/*
* Copyright 2002-2011 the original author 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;
import org.springframework.beans.factory.Aware;
import org.springframework.util.StringValueResolver;
/**
* Interface to be implemented by any object that wishes to be notified of a
* <b>StringValueResolver</b> for the <b> resolution of embedded definition values.
*
* <p>This is an alternative to a full ConfigurableBeanFactory dependency via the
* ApplicationContextAware/BeanFactoryAware interfaces.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.0.3
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#resolveEmbeddedValue
*/
public interface EmbeddedValueResolverAware extends Aware {
/**
* Set the StringValueResolver to use for resolving embedded definition values.
*/
void setEmbeddedValueResolver(StringValueResolver resolver);
}
/*
* Copyright 2002-2011 the original author 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;
import org.springframework.beans.factory.Aware;
import org.springframework.util.StringValueResolver;
/**
* Interface to be implemented by any object that wishes to be notified of a
* <b>StringValueResolver</b> for the <b> resolution of embedded definition values.
*
* <p>This is an alternative to a full ConfigurableBeanFactory dependency via the
* ApplicationContextAware/BeanFactoryAware interfaces.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.0.3
* @see org.springframework.beans.factory.config.ConfigurableBeanFactory#resolveEmbeddedValue
*/
public interface EmbeddedValueResolverAware extends Aware {
/**
* Set the StringValueResolver to use for resolving embedded definition values.
*/
void setEmbeddedValueResolver(StringValueResolver resolver);
}

View File

@@ -1,177 +1,177 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.Annotation;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
/**
* Convenient adapter for programmatic registration of annotated bean classes.
* This is an alternative to {@link ClassPathBeanDefinitionScanner}, applying
* the same resolution of annotations but for explicitly registered classes only.
*
* @author Juergen Hoeller
* @author Chris Beams
* @author Sam Brannen
* @since 3.0
* @see AnnotationConfigApplicationContext#register
*/
public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private Environment environment;
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry.
* If the registry is {@link EnvironmentCapable}, e.g. is an {@code ApplicationContext},
* the {@link Environment} will be inherited, otherwise a new
* {@link StandardEnvironment} will be created and used.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @see #AnnotatedBeanDefinitionReader(BeanDefinitionRegistry, Environment)
* @see #setEnvironment(Environment)
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry and using
* the given {@link Environment}.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @param environment the {@code Environment} to use when evaluating bean definition
* profiles.
* @since 3.1
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.environment = environment;
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
/**
* Return the BeanDefinitionRegistry that this scanner operates on.
*/
public final BeanDefinitionRegistry getRegistry() {
return this.registry;
}
/**
* Set the Environment to use when evaluating whether
* {@link Profile @Profile}-annotated component classes should be registered.
* <p>The default is a {@link StandardEnvironment}.
* @see #registerBean(Class, String, Class...)
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* Set the BeanNameGenerator to use for detected bean classes.
* <p>The default is a {@link AnnotationBeanNameGenerator}.
*/
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());
}
/**
* Set the ScopeMetadataResolver to use for detected bean classes.
* <p>The default is an {@link AnnotationScopeMetadataResolver}.
*/
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
this.scopeMetadataResolver = (scopeMetadataResolver != null ? scopeMetadataResolver
: new AnnotationScopeMetadataResolver());
}
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
public void registerBean(Class<?> annotatedClass) {
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
}
public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
registerBean(annotatedClass, null, qualifiers);
}
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
AnnotationMetadata metadata = abd.getMetadata();
if (ProfileHelper.isProfileAnnotationPresent(metadata)) {
if (!this.environment.acceptsProfiles(ProfileHelper.getCandidateProfiles(metadata))) {
return;
}
}
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class.equals(qualifier)) {
abd.setPrimary(true);
} else if (Lazy.class.equals(qualifier)) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
/**
* Get the Environment from the given registry if possible, otherwise return a new
* StandardEnvironment.
*/
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry instanceof EnvironmentCapable) {
return ((EnvironmentCapable) registry).getEnvironment();
}
return new StandardEnvironment();
}
}
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.Annotation;
import org.springframework.beans.factory.annotation.AnnotatedGenericBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.AutowireCandidateQualifier;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanNameGenerator;
import org.springframework.core.env.Environment;
import org.springframework.core.env.EnvironmentCapable;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
/**
* Convenient adapter for programmatic registration of annotated bean classes.
* This is an alternative to {@link ClassPathBeanDefinitionScanner}, applying
* the same resolution of annotations but for explicitly registered classes only.
*
* @author Juergen Hoeller
* @author Chris Beams
* @author Sam Brannen
* @since 3.0
* @see AnnotationConfigApplicationContext#register
*/
public class AnnotatedBeanDefinitionReader {
private final BeanDefinitionRegistry registry;
private Environment environment;
private BeanNameGenerator beanNameGenerator = new AnnotationBeanNameGenerator();
private ScopeMetadataResolver scopeMetadataResolver = new AnnotationScopeMetadataResolver();
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry.
* If the registry is {@link EnvironmentCapable}, e.g. is an {@code ApplicationContext},
* the {@link Environment} will be inherited, otherwise a new
* {@link StandardEnvironment} will be created and used.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @see #AnnotatedBeanDefinitionReader(BeanDefinitionRegistry, Environment)
* @see #setEnvironment(Environment)
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry) {
this(registry, getOrCreateEnvironment(registry));
}
/**
* Create a new {@code AnnotatedBeanDefinitionReader} for the given registry and using
* the given {@link Environment}.
* @param registry the {@code BeanFactory} to load bean definitions into,
* in the form of a {@code BeanDefinitionRegistry}
* @param environment the {@code Environment} to use when evaluating bean definition
* profiles.
* @since 3.1
*/
public AnnotatedBeanDefinitionReader(BeanDefinitionRegistry registry, Environment environment) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
Assert.notNull(environment, "Environment must not be null");
this.registry = registry;
this.environment = environment;
AnnotationConfigUtils.registerAnnotationConfigProcessors(this.registry);
}
/**
* Return the BeanDefinitionRegistry that this scanner operates on.
*/
public final BeanDefinitionRegistry getRegistry() {
return this.registry;
}
/**
* Set the Environment to use when evaluating whether
* {@link Profile @Profile}-annotated component classes should be registered.
* <p>The default is a {@link StandardEnvironment}.
* @see #registerBean(Class, String, Class...)
*/
public void setEnvironment(Environment environment) {
this.environment = environment;
}
/**
* Set the BeanNameGenerator to use for detected bean classes.
* <p>The default is a {@link AnnotationBeanNameGenerator}.
*/
public void setBeanNameGenerator(BeanNameGenerator beanNameGenerator) {
this.beanNameGenerator = (beanNameGenerator != null ? beanNameGenerator : new AnnotationBeanNameGenerator());
}
/**
* Set the ScopeMetadataResolver to use for detected bean classes.
* <p>The default is an {@link AnnotationScopeMetadataResolver}.
*/
public void setScopeMetadataResolver(ScopeMetadataResolver scopeMetadataResolver) {
this.scopeMetadataResolver = (scopeMetadataResolver != null ? scopeMetadataResolver
: new AnnotationScopeMetadataResolver());
}
public void register(Class<?>... annotatedClasses) {
for (Class<?> annotatedClass : annotatedClasses) {
registerBean(annotatedClass);
}
}
public void registerBean(Class<?> annotatedClass) {
registerBean(annotatedClass, null, (Class<? extends Annotation>[]) null);
}
public void registerBean(Class<?> annotatedClass, Class<? extends Annotation>... qualifiers) {
registerBean(annotatedClass, null, qualifiers);
}
public void registerBean(Class<?> annotatedClass, String name, Class<? extends Annotation>... qualifiers) {
AnnotatedGenericBeanDefinition abd = new AnnotatedGenericBeanDefinition(annotatedClass);
AnnotationMetadata metadata = abd.getMetadata();
if (ProfileHelper.isProfileAnnotationPresent(metadata)) {
if (!this.environment.acceptsProfiles(ProfileHelper.getCandidateProfiles(metadata))) {
return;
}
}
ScopeMetadata scopeMetadata = this.scopeMetadataResolver.resolveScopeMetadata(abd);
abd.setScope(scopeMetadata.getScopeName());
String beanName = (name != null ? name : this.beanNameGenerator.generateBeanName(abd, this.registry));
AnnotationConfigUtils.processCommonDefinitionAnnotations(abd);
if (qualifiers != null) {
for (Class<? extends Annotation> qualifier : qualifiers) {
if (Primary.class.equals(qualifier)) {
abd.setPrimary(true);
} else if (Lazy.class.equals(qualifier)) {
abd.setLazyInit(true);
} else {
abd.addQualifier(new AutowireCandidateQualifier(qualifier));
}
}
}
BeanDefinitionHolder definitionHolder = new BeanDefinitionHolder(abd, beanName);
definitionHolder = AnnotationConfigUtils.applyScopedProxyMode(scopeMetadata, definitionHolder, this.registry);
BeanDefinitionReaderUtils.registerBeanDefinition(definitionHolder, this.registry);
}
/**
* Get the Environment from the given registry if possible, otherwise return a new
* StandardEnvironment.
*/
private static Environment getOrCreateEnvironment(BeanDefinitionRegistry registry) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry instanceof EnvironmentCapable) {
return ((EnvironmentCapable) registry).getEnvironment();
}
return new StandardEnvironment();
}
}

View File

@@ -1,54 +1,54 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
import java.lang.annotation.Documented;
/**
* Beans on which the current bean depends. Any beans specified are guaranteed to be
* created by the container before this bean. Used infrequently in cases where a bean
* does not explicitly depend on another through properties or constructor arguments,
* but rather depends on the side effects of another bean's initialization.
* <p>Note: This attribute will not be inherited by child bean definitions,
* hence it needs to be specified per concrete bean definition.
*
* <p>May be used on any class directly or indirectly annotated with
* {@link org.springframework.stereotype.Component} or on methods annotated
* with {@link Bean}.
*
* <p>Using {@link DependsOn} at the class level has no effect unless component-scanning
* is being used. If a {@link DependsOn}-annotated class is declared via XML,
* {@link DependsOn} annotation metadata is ignored, and
* {@code <bean depends-on="..."/>} is respected instead.
*
* @author Juergen Hoeller
* @since 3.0
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DependsOn {
String[] value() default {};
}
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.lang.annotation.Target;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Inherited;
import java.lang.annotation.Documented;
/**
* Beans on which the current bean depends. Any beans specified are guaranteed to be
* created by the container before this bean. Used infrequently in cases where a bean
* does not explicitly depend on another through properties or constructor arguments,
* but rather depends on the side effects of another bean's initialization.
* <p>Note: This attribute will not be inherited by child bean definitions,
* hence it needs to be specified per concrete bean definition.
*
* <p>May be used on any class directly or indirectly annotated with
* {@link org.springframework.stereotype.Component} or on methods annotated
* with {@link Bean}.
*
* <p>Using {@link DependsOn} at the class level has no effect unless component-scanning
* is being used. If a {@link DependsOn}-annotated class is declared via XML,
* {@link DependsOn} annotation metadata is ignored, and
* {@code <bean depends-on="..."/>} is respected instead.
*
* @author Juergen Hoeller
* @since 3.0
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface DependsOn {
String[] value() default {};
}

View File

@@ -1,111 +1,111 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
/**
* Simple {@link ScopeMetadataResolver} implementation that follows JSR-330 scoping rules:
* defaulting to prototype scope unless {@link javax.inject.Singleton} is present.
*
* <p>This scope resolver can be used with {@link ClassPathBeanDefinitionScanner} and
* {@link AnnotatedBeanDefinitionReader} for standard JSR-330 compliance. However,
* in practice, you will typically use Spring's rich default scoping instead - or extend
* this resolver with custom scoping annotations that point to extended Spring scopes.
*
* @author Juergen Hoeller
* @since 3.0
* @see #registerScope
* @see #resolveScopeName
* @see ClassPathBeanDefinitionScanner#setScopeMetadataResolver
* @see AnnotatedBeanDefinitionReader#setScopeMetadataResolver
*/
public class Jsr330ScopeMetadataResolver implements ScopeMetadataResolver {
private final Map<String, String> scopeMap = new HashMap<String, String>();
public Jsr330ScopeMetadataResolver() {
registerScope("javax.inject.Singleton", BeanDefinition.SCOPE_SINGLETON);
}
/**
* Register an extended JSR-330 scope annotation, mapping it onto a
* specific Spring scope by name.
* @param annotationType the JSR-330 annotation type as a Class
* @param scopeName the Spring scope name
*/
public final void registerScope(Class annotationType, String scopeName) {
this.scopeMap.put(annotationType.getName(), scopeName);
}
/**
* Register an extended JSR-330 scope annotation, mapping it onto a
* specific Spring scope by name.
* @param annotationType the JSR-330 annotation type by name
* @param scopeName the Spring scope name
*/
public final void registerScope(String annotationType, String scopeName) {
this.scopeMap.put(annotationType, scopeName);
}
/**
* Resolve the given annotation type into a named Spring scope.
* <p>The default implementation simply checks against registered scopes.
* Can be overridden for custom mapping rules, e.g. naming conventions.
* @param annotationType the JSR-330 annotation type
* @return the Spring scope name
*/
protected String resolveScopeName(String annotationType) {
return this.scopeMap.get(annotationType);
}
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
Set<String> annTypes = annDef.getMetadata().getAnnotationTypes();
String found = null;
for (String annType : annTypes) {
Set<String> metaAnns = annDef.getMetadata().getMetaAnnotationTypes(annType);
if (metaAnns.contains("javax.inject.Scope")) {
if (found != null) {
throw new IllegalStateException("Found ambiguous scope annotations on bean class [" +
definition.getBeanClassName() + "]: " + found + ", " + annType);
}
found = annType;
String scopeName = resolveScopeName(annType);
if (scopeName == null) {
throw new IllegalStateException(
"Unsupported scope annotation - not mapped onto Spring scope name: " + annType);
}
metadata.setScopeName(scopeName);
}
}
}
return metadata;
}
}
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinition;
/**
* Simple {@link ScopeMetadataResolver} implementation that follows JSR-330 scoping rules:
* defaulting to prototype scope unless {@link javax.inject.Singleton} is present.
*
* <p>This scope resolver can be used with {@link ClassPathBeanDefinitionScanner} and
* {@link AnnotatedBeanDefinitionReader} for standard JSR-330 compliance. However,
* in practice, you will typically use Spring's rich default scoping instead - or extend
* this resolver with custom scoping annotations that point to extended Spring scopes.
*
* @author Juergen Hoeller
* @since 3.0
* @see #registerScope
* @see #resolveScopeName
* @see ClassPathBeanDefinitionScanner#setScopeMetadataResolver
* @see AnnotatedBeanDefinitionReader#setScopeMetadataResolver
*/
public class Jsr330ScopeMetadataResolver implements ScopeMetadataResolver {
private final Map<String, String> scopeMap = new HashMap<String, String>();
public Jsr330ScopeMetadataResolver() {
registerScope("javax.inject.Singleton", BeanDefinition.SCOPE_SINGLETON);
}
/**
* Register an extended JSR-330 scope annotation, mapping it onto a
* specific Spring scope by name.
* @param annotationType the JSR-330 annotation type as a Class
* @param scopeName the Spring scope name
*/
public final void registerScope(Class annotationType, String scopeName) {
this.scopeMap.put(annotationType.getName(), scopeName);
}
/**
* Register an extended JSR-330 scope annotation, mapping it onto a
* specific Spring scope by name.
* @param annotationType the JSR-330 annotation type by name
* @param scopeName the Spring scope name
*/
public final void registerScope(String annotationType, String scopeName) {
this.scopeMap.put(annotationType, scopeName);
}
/**
* Resolve the given annotation type into a named Spring scope.
* <p>The default implementation simply checks against registered scopes.
* Can be overridden for custom mapping rules, e.g. naming conventions.
* @param annotationType the JSR-330 annotation type
* @return the Spring scope name
*/
protected String resolveScopeName(String annotationType) {
return this.scopeMap.get(annotationType);
}
public ScopeMetadata resolveScopeMetadata(BeanDefinition definition) {
ScopeMetadata metadata = new ScopeMetadata();
metadata.setScopeName(BeanDefinition.SCOPE_PROTOTYPE);
if (definition instanceof AnnotatedBeanDefinition) {
AnnotatedBeanDefinition annDef = (AnnotatedBeanDefinition) definition;
Set<String> annTypes = annDef.getMetadata().getAnnotationTypes();
String found = null;
for (String annType : annTypes) {
Set<String> metaAnns = annDef.getMetadata().getMetaAnnotationTypes(annType);
if (metaAnns.contains("javax.inject.Scope")) {
if (found != null) {
throw new IllegalStateException("Found ambiguous scope annotations on bean class [" +
definition.getBeanClassName() + "]: " + found + ", " + annType);
}
found = annType;
String scopeName = resolveScopeName(annType);
if (scopeName == null) {
throw new IllegalStateException(
"Unsupported scope annotation - not mapped onto Spring scope name: " + annType);
}
metadata.setScopeName(scopeName);
}
}
}
return metadata;
}
}

View File

@@ -1,43 +1,43 @@
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
/**
* Delegate factory class used to just introduce an AOP framework dependency
* when actually creating a scoped proxy.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.aop.scope.ScopedProxyUtils#createScopedProxy
*/
class ScopedProxyCreator {
public static BeanDefinitionHolder createScopedProxy(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}
public static String getTargetBeanName(String originalBeanName) {
return ScopedProxyUtils.getTargetBeanName(originalBeanName);
}
}
/*
* Copyright 2002-2009 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.context.annotation;
import org.springframework.aop.scope.ScopedProxyUtils;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
/**
* Delegate factory class used to just introduce an AOP framework dependency
* when actually creating a scoped proxy.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.aop.scope.ScopedProxyUtils#createScopedProxy
*/
class ScopedProxyCreator {
public static BeanDefinitionHolder createScopedProxy(
BeanDefinitionHolder definitionHolder, BeanDefinitionRegistry registry, boolean proxyTargetClass) {
return ScopedProxyUtils.createScopedProxy(definitionHolder, registry, proxyTargetClass);
}
public static String getTargetBeanName(String originalBeanName) {
return ScopedProxyUtils.getTargetBeanName(originalBeanName);
}
}

View File

@@ -1,73 +1,73 @@
/*
* Copyright 2002-2009 the original author 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.event;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
/**
* {@link SmartApplicationListener} adapter that determines supported event types
* through introspecting the generically declared type of the target listener.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.context.ApplicationListener#onApplicationEvent
*/
public class GenericApplicationListenerAdapter implements SmartApplicationListener {
private final ApplicationListener delegate;
/**
* Create a new GenericApplicationListener for the given delegate.
* @param delegate the delegate listener to be invoked
*/
public GenericApplicationListenerAdapter(ApplicationListener delegate) {
Assert.notNull(delegate, "Delegate listener must not be null");
this.delegate = delegate;
}
@SuppressWarnings("unchecked")
public void onApplicationEvent(ApplicationEvent event) {
this.delegate.onApplicationEvent(event);
}
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
Class typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class);
if (typeArg == null || typeArg.equals(ApplicationEvent.class)) {
Class targetClass = AopUtils.getTargetClass(this.delegate);
if (targetClass != this.delegate.getClass()) {
typeArg = GenericTypeResolver.resolveTypeArgument(targetClass, ApplicationListener.class);
}
}
return (typeArg == null || typeArg.isAssignableFrom(eventType));
}
public boolean supportsSourceType(Class<?> sourceType) {
return true;
}
public int getOrder() {
return (this.delegate instanceof Ordered ? ((Ordered) this.delegate).getOrder() : Ordered.LOWEST_PRECEDENCE);
}
}
/*
* Copyright 2002-2009 the original author 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.event;
import org.springframework.aop.support.AopUtils;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.GenericTypeResolver;
import org.springframework.core.Ordered;
import org.springframework.util.Assert;
/**
* {@link SmartApplicationListener} adapter that determines supported event types
* through introspecting the generically declared type of the target listener.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.context.ApplicationListener#onApplicationEvent
*/
public class GenericApplicationListenerAdapter implements SmartApplicationListener {
private final ApplicationListener delegate;
/**
* Create a new GenericApplicationListener for the given delegate.
* @param delegate the delegate listener to be invoked
*/
public GenericApplicationListenerAdapter(ApplicationListener delegate) {
Assert.notNull(delegate, "Delegate listener must not be null");
this.delegate = delegate;
}
@SuppressWarnings("unchecked")
public void onApplicationEvent(ApplicationEvent event) {
this.delegate.onApplicationEvent(event);
}
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
Class typeArg = GenericTypeResolver.resolveTypeArgument(this.delegate.getClass(), ApplicationListener.class);
if (typeArg == null || typeArg.equals(ApplicationEvent.class)) {
Class targetClass = AopUtils.getTargetClass(this.delegate);
if (targetClass != this.delegate.getClass()) {
typeArg = GenericTypeResolver.resolveTypeArgument(targetClass, ApplicationListener.class);
}
}
return (typeArg == null || typeArg.isAssignableFrom(eventType));
}
public boolean supportsSourceType(Class<?> sourceType) {
return true;
}
public int getOrder() {
return (this.delegate instanceof Ordered ? ((Ordered) this.delegate).getOrder() : Ordered.LOWEST_PRECEDENCE);
}
}

View File

@@ -1,42 +1,42 @@
/*
* Copyright 2002-2009 the original author 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.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
/**
* Extended variant of the standard {@link ApplicationListener} interface,
* exposing further metadata such as the supported event type.
*
* @author Juergen Hoeller
* @since 3.0
*/
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
/**
* Determine whether this listener actually supports the given event type.
*/
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
/**
* Determine whether this listener actually supports the given source type.
*/
boolean supportsSourceType(Class<?> sourceType);
}
/*
* Copyright 2002-2009 the original author 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.event;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.core.Ordered;
/**
* Extended variant of the standard {@link ApplicationListener} interface,
* exposing further metadata such as the supported event type.
*
* @author Juergen Hoeller
* @since 3.0
*/
public interface SmartApplicationListener extends ApplicationListener<ApplicationEvent>, Ordered {
/**
* Determine whether this listener actually supports the given event type.
*/
boolean supportsEventType(Class<? extends ApplicationEvent> eventType);
/**
* Determine whether this listener actually supports the given source type.
*/
boolean supportsSourceType(Class<?> sourceType);
}

View File

@@ -1,55 +1,55 @@
/*
* Copyright 2002-2010 the original author 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.expression;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
/**
* EL property accessor that knows how to traverse the beans and contextual objects
* of a Spring {@link org.springframework.beans.factory.config.BeanExpressionContext}.
*
* @author Juergen Hoeller
* @author Andy Clement
* @since 3.0
*/
public class BeanExpressionContextAccessor implements PropertyAccessor {
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
return ((BeanExpressionContext) target).containsObject(name);
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(((BeanExpressionContext) target).getObject(name));
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
return false;
}
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
throw new AccessException("Beans in a BeanFactory are read-only");
}
public Class[] getSpecificTargetClasses() {
return new Class[] {BeanExpressionContext.class};
}
}
/*
* Copyright 2002-2010 the original author 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.expression;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
/**
* EL property accessor that knows how to traverse the beans and contextual objects
* of a Spring {@link org.springframework.beans.factory.config.BeanExpressionContext}.
*
* @author Juergen Hoeller
* @author Andy Clement
* @since 3.0
*/
public class BeanExpressionContextAccessor implements PropertyAccessor {
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
return ((BeanExpressionContext) target).containsObject(name);
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(((BeanExpressionContext) target).getObject(name));
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
return false;
}
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
throw new AccessException("Beans in a BeanFactory are read-only");
}
public Class[] getSpecificTargetClasses() {
return new Class[] {BeanExpressionContext.class};
}
}

View File

@@ -1,55 +1,55 @@
/*
* Copyright 2002-2009 the original author 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.expression;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
/**
* EL property accessor that knows how to traverse the beans of a
* Spring {@link org.springframework.beans.factory.BeanFactory}.
*
* @author Juergen Hoeller
* @author Andy Clement
* @since 3.0
*/
public class BeanFactoryAccessor implements PropertyAccessor {
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
return (((BeanFactory) target).containsBean(name));
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(((BeanFactory) target).getBean(name));
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
return false;
}
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
throw new AccessException("Beans in a BeanFactory are read-only");
}
public Class[] getSpecificTargetClasses() {
return new Class[] {BeanFactory.class};
}
}
/*
* Copyright 2002-2009 the original author 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.expression;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
/**
* EL property accessor that knows how to traverse the beans of a
* Spring {@link org.springframework.beans.factory.BeanFactory}.
*
* @author Juergen Hoeller
* @author Andy Clement
* @since 3.0
*/
public class BeanFactoryAccessor implements PropertyAccessor {
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
return (((BeanFactory) target).containsBean(name));
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
return new TypedValue(((BeanFactory) target).getBean(name));
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
return false;
}
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
throw new AccessException("Beans in a BeanFactory are read-only");
}
public Class[] getSpecificTargetClasses() {
return new Class[] {BeanFactory.class};
}
}

View File

@@ -1,51 +1,51 @@
/*
* Copyright 2002-2010 the original author 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.expression;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.expression.AccessException;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.util.Assert;
/**
* EL bean resolver that operates against a Spring
* {@link org.springframework.beans.factory.BeanFactory}.
*
* @author Juergen Hoeller
* @since 3.0.4
*/
public class BeanFactoryResolver implements BeanResolver {
private final BeanFactory beanFactory;
public BeanFactoryResolver(BeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
}
public Object resolve(EvaluationContext context, String beanName) throws AccessException {
try {
return this.beanFactory.getBean(beanName);
}
catch (BeansException ex) {
throw new AccessException("Could not resolve bean reference against BeanFactory", ex);
}
}
}
/*
* Copyright 2002-2010 the original author 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.expression;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.expression.AccessException;
import org.springframework.expression.BeanResolver;
import org.springframework.expression.EvaluationContext;
import org.springframework.util.Assert;
/**
* EL bean resolver that operates against a Spring
* {@link org.springframework.beans.factory.BeanFactory}.
*
* @author Juergen Hoeller
* @since 3.0.4
*/
public class BeanFactoryResolver implements BeanResolver {
private final BeanFactory beanFactory;
public BeanFactoryResolver(BeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
}
public Object resolve(EvaluationContext context, String beanName) throws AccessException {
try {
return this.beanFactory.getBean(beanName);
}
catch (BeansException ex) {
throw new AccessException("Could not resolve bean reference against BeanFactory", ex);
}
}
}

View File

@@ -1,84 +1,84 @@
/*
* Copyright 2002-2010 the original author 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.expression;
import java.util.Map;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
/**
* EL property accessor that knows how to traverse the keys
* of a standard {@link java.util.Map}.
*
* @author Juergen Hoeller
* @author Andy Clement
* @since 3.0
*/
public class MapAccessor implements PropertyAccessor {
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
Map map = (Map) target;
return map.containsKey(name);
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
Map map = (Map) target;
Object value = map.get(name);
if (value == null && !map.containsKey(name)) {
throw new MapAccessException(name);
}
return new TypedValue(value);
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
return true;
}
@SuppressWarnings("unchecked")
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
Map map = (Map) target;
map.put(name, newValue);
}
public Class[] getSpecificTargetClasses() {
return new Class[] {Map.class};
}
/**
* Exception thrown from <code>read</code> in order to reset a cached
* PropertyAccessor, allowing other accessors to have a try.
*/
private static class MapAccessException extends AccessException {
private final String key;
public MapAccessException(String key) {
super(null);
this.key = key;
}
@Override
public String getMessage() {
return "Map does not contain a value for key '" + this.key + "'";
}
}
}
/*
* Copyright 2002-2010 the original author 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.expression;
import java.util.Map;
import org.springframework.expression.AccessException;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.PropertyAccessor;
import org.springframework.expression.TypedValue;
/**
* EL property accessor that knows how to traverse the keys
* of a standard {@link java.util.Map}.
*
* @author Juergen Hoeller
* @author Andy Clement
* @since 3.0
*/
public class MapAccessor implements PropertyAccessor {
public boolean canRead(EvaluationContext context, Object target, String name) throws AccessException {
Map map = (Map) target;
return map.containsKey(name);
}
public TypedValue read(EvaluationContext context, Object target, String name) throws AccessException {
Map map = (Map) target;
Object value = map.get(name);
if (value == null && !map.containsKey(name)) {
throw new MapAccessException(name);
}
return new TypedValue(value);
}
public boolean canWrite(EvaluationContext context, Object target, String name) throws AccessException {
return true;
}
@SuppressWarnings("unchecked")
public void write(EvaluationContext context, Object target, String name, Object newValue) throws AccessException {
Map map = (Map) target;
map.put(name, newValue);
}
public Class[] getSpecificTargetClasses() {
return new Class[] {Map.class};
}
/**
* Exception thrown from <code>read</code> in order to reset a cached
* PropertyAccessor, allowing other accessors to have a try.
*/
private static class MapAccessException extends AccessException {
private final String key;
public MapAccessException(String key) {
super(null);
this.key = key;
}
@Override
public String getMessage() {
return "Map does not contain a value for key '" + this.key + "'";
}
}
}

View File

@@ -1,153 +1,153 @@
/*
* Copyright 2002-2010 the original author 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.expression;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanExpressionException;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.core.convert.ConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Standard implementation of the
* {@link org.springframework.beans.factory.config.BeanExpressionResolver}
* interface, parsing and evaluating Spring EL using Spring's expression module.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.expression.ExpressionParser
* @see org.springframework.expression.spel.standard.SpelExpressionParser
* @see org.springframework.expression.spel.support.StandardEvaluationContext
*/
public class StandardBeanExpressionResolver implements BeanExpressionResolver {
/** Default expression prefix: "#{" */
public static final String DEFAULT_EXPRESSION_PREFIX = "#{";
/** Default expression suffix: "}" */
public static final String DEFAULT_EXPRESSION_SUFFIX = "}";
private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
private ExpressionParser expressionParser = new SpelExpressionParser();
private final Map<String, Expression> expressionCache = new ConcurrentHashMap<String, Expression>();
private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache =
new ConcurrentHashMap<BeanExpressionContext, StandardEvaluationContext>();
private final ParserContext beanExpressionParserContext = new ParserContext() {
public boolean isTemplate() {
return true;
}
public String getExpressionPrefix() {
return expressionPrefix;
}
public String getExpressionSuffix() {
return expressionSuffix;
}
};
/**
* Set the prefix that an expression string starts with.
* The default is "#{".
* @see #DEFAULT_EXPRESSION_PREFIX
*/
public void setExpressionPrefix(String expressionPrefix) {
Assert.hasText(expressionPrefix, "Expression prefix must not be empty");
this.expressionPrefix = expressionPrefix;
}
/**
* Set the suffix that an expression string ends with.
* The default is "}".
* @see #DEFAULT_EXPRESSION_SUFFIX
*/
public void setExpressionSuffix(String expressionSuffix) {
Assert.hasText(expressionSuffix, "Expression suffix must not be empty");
this.expressionSuffix = expressionSuffix;
}
/**
* Specify the EL parser to use for expression parsing.
* <p>Default is a {@link org.springframework.expression.spel.standard.SpelExpressionParser},
* compatible with standard Unified EL style expression syntax.
*/
public void setExpressionParser(ExpressionParser expressionParser) {
Assert.notNull(expressionParser, "ExpressionParser must not be null");
this.expressionParser = expressionParser;
}
public Object evaluate(String value, BeanExpressionContext evalContext) throws BeansException {
if (!StringUtils.hasLength(value)) {
return value;
}
try {
Expression expr = this.expressionCache.get(value);
if (expr == null) {
expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
this.expressionCache.put(value, expr);
}
StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
if (sec == null) {
sec = new StandardEvaluationContext();
sec.setRootObject(evalContext);
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());
sec.addPropertyAccessor(new EnvironmentAccessor());
sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
if (conversionService != null) {
sec.setTypeConverter(new StandardTypeConverter(conversionService));
}
customizeEvaluationContext(sec);
this.evaluationCache.put(evalContext, sec);
}
return expr.getValue(sec);
}
catch (Exception ex) {
throw new BeanExpressionException("Expression parsing failed", ex);
}
}
/**
* Template method for customizing the expression evaluation context.
* <p>The default implementation is empty.
*/
protected void customizeEvaluationContext(StandardEvaluationContext evalContext) {
}
}
/*
* Copyright 2002-2010 the original author 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.expression;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanExpressionException;
import org.springframework.beans.factory.config.BeanExpressionContext;
import org.springframework.beans.factory.config.BeanExpressionResolver;
import org.springframework.core.convert.ConversionService;
import org.springframework.expression.Expression;
import org.springframework.expression.ExpressionParser;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.expression.spel.support.StandardTypeConverter;
import org.springframework.expression.spel.support.StandardTypeLocator;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Standard implementation of the
* {@link org.springframework.beans.factory.config.BeanExpressionResolver}
* interface, parsing and evaluating Spring EL using Spring's expression module.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.expression.ExpressionParser
* @see org.springframework.expression.spel.standard.SpelExpressionParser
* @see org.springframework.expression.spel.support.StandardEvaluationContext
*/
public class StandardBeanExpressionResolver implements BeanExpressionResolver {
/** Default expression prefix: "#{" */
public static final String DEFAULT_EXPRESSION_PREFIX = "#{";
/** Default expression suffix: "}" */
public static final String DEFAULT_EXPRESSION_SUFFIX = "}";
private String expressionPrefix = DEFAULT_EXPRESSION_PREFIX;
private String expressionSuffix = DEFAULT_EXPRESSION_SUFFIX;
private ExpressionParser expressionParser = new SpelExpressionParser();
private final Map<String, Expression> expressionCache = new ConcurrentHashMap<String, Expression>();
private final Map<BeanExpressionContext, StandardEvaluationContext> evaluationCache =
new ConcurrentHashMap<BeanExpressionContext, StandardEvaluationContext>();
private final ParserContext beanExpressionParserContext = new ParserContext() {
public boolean isTemplate() {
return true;
}
public String getExpressionPrefix() {
return expressionPrefix;
}
public String getExpressionSuffix() {
return expressionSuffix;
}
};
/**
* Set the prefix that an expression string starts with.
* The default is "#{".
* @see #DEFAULT_EXPRESSION_PREFIX
*/
public void setExpressionPrefix(String expressionPrefix) {
Assert.hasText(expressionPrefix, "Expression prefix must not be empty");
this.expressionPrefix = expressionPrefix;
}
/**
* Set the suffix that an expression string ends with.
* The default is "}".
* @see #DEFAULT_EXPRESSION_SUFFIX
*/
public void setExpressionSuffix(String expressionSuffix) {
Assert.hasText(expressionSuffix, "Expression suffix must not be empty");
this.expressionSuffix = expressionSuffix;
}
/**
* Specify the EL parser to use for expression parsing.
* <p>Default is a {@link org.springframework.expression.spel.standard.SpelExpressionParser},
* compatible with standard Unified EL style expression syntax.
*/
public void setExpressionParser(ExpressionParser expressionParser) {
Assert.notNull(expressionParser, "ExpressionParser must not be null");
this.expressionParser = expressionParser;
}
public Object evaluate(String value, BeanExpressionContext evalContext) throws BeansException {
if (!StringUtils.hasLength(value)) {
return value;
}
try {
Expression expr = this.expressionCache.get(value);
if (expr == null) {
expr = this.expressionParser.parseExpression(value, this.beanExpressionParserContext);
this.expressionCache.put(value, expr);
}
StandardEvaluationContext sec = this.evaluationCache.get(evalContext);
if (sec == null) {
sec = new StandardEvaluationContext();
sec.setRootObject(evalContext);
sec.addPropertyAccessor(new BeanExpressionContextAccessor());
sec.addPropertyAccessor(new BeanFactoryAccessor());
sec.addPropertyAccessor(new MapAccessor());
sec.addPropertyAccessor(new EnvironmentAccessor());
sec.setBeanResolver(new BeanFactoryResolver(evalContext.getBeanFactory()));
sec.setTypeLocator(new StandardTypeLocator(evalContext.getBeanFactory().getBeanClassLoader()));
ConversionService conversionService = evalContext.getBeanFactory().getConversionService();
if (conversionService != null) {
sec.setTypeConverter(new StandardTypeConverter(conversionService));
}
customizeEvaluationContext(sec);
this.evaluationCache.put(evalContext, sec);
}
return expr.getValue(sec);
}
catch (Exception ex) {
throw new BeanExpressionException("Expression parsing failed", ex);
}
}
/**
* Template method for customizing the expression evaluation context.
* <p>The default implementation is empty.
*/
protected void customizeEvaluationContext(StandardEvaluationContext evalContext) {
}
}

View File

@@ -1,134 +1,134 @@
/*
* Copyright 2002-2009 the original author 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 org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/**
* Convenient application context with built-in XML support.
* This is a flexible alternative to {@link ClassPathXmlApplicationContext}
* and {@link FileSystemXmlApplicationContext}, to be configured via setters,
* with an eventual {@link #refresh()} call activating the context.
*
* <p>In case of multiple configuration files, bean definitions in later files
* will override those defined in earlier files. This can be leveraged to
* deliberately override certain bean definitions via an extra configuration file.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.0
* @see #load
* @see XmlBeanDefinitionReader
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
*/
public class GenericXmlApplicationContext extends GenericApplicationContext {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
/**
* Create a new GenericXmlApplicationContext that needs to be
* {@linkplain #load loaded} and then manually {@link #refresh refreshed}.
*/
public GenericXmlApplicationContext() {
reader.setEnvironment(this.getEnvironment());
}
/**
* Create a new GenericXmlApplicationContext, loading bean definitions
* from the given resources and automatically refreshing the context.
* @param resources the resources to load from
*/
public GenericXmlApplicationContext(Resource... resources) {
load(resources);
refresh();
}
/**
* Create a new GenericXmlApplicationContext, loading bean definitions
* from the given resource locations and automatically refreshing the context.
* @param resourceLocations the resources to load from
*/
public GenericXmlApplicationContext(String... resourceLocations) {
load(resourceLocations);
refresh();
}
/**
* Create a new GenericXmlApplicationContext, loading bean definitions
* from the given resource locations and automatically refreshing the context.
* @param relativeClass class whose package will be used as a prefix when
* loading each specified resource name
* @param resourceNames relatively-qualified names of resources to load
*/
public GenericXmlApplicationContext(Class<?> relativeClass, String... resourceNames) {
load(relativeClass, resourceNames);
refresh();
}
/**
* Set whether to use XML validation. Default is <code>true</code>.
*/
public void setValidating(boolean validating) {
this.reader.setValidating(validating);
}
/**
* {@inheritDoc}
* <p>Delegates the given environment to underlying {@link XmlBeanDefinitionReader}.
* Should be called before any call to {@link #load}.
*/
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(this.getEnvironment());
}
/**
* Load bean definitions from the given XML resources.
* @param resources one or more resources to load from
*/
public void load(Resource... resources) {
this.reader.loadBeanDefinitions(resources);
}
/**
* Load bean definitions from the given XML resources.
* @param resourceLocations one or more resource locations to load from
*/
public void load(String... resourceLocations) {
this.reader.loadBeanDefinitions(resourceLocations);
}
/**
* Load bean definitions from the given XML resources.
* @param relativeClass class whose package will be used as a prefix when
* loading each specified resource name
* @param resourceNames relatively-qualified names of resources to load
*/
public void load(Class<?> relativeClass, String... resourceNames) {
Resource[] resources = new Resource[resourceNames.length];
for (int i = 0; i < resourceNames.length; i++) {
resources[i] = new ClassPathResource(resourceNames[i], relativeClass);
}
this.load(resources);
}
}
/*
* Copyright 2002-2009 the original author 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 org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
/**
* Convenient application context with built-in XML support.
* This is a flexible alternative to {@link ClassPathXmlApplicationContext}
* and {@link FileSystemXmlApplicationContext}, to be configured via setters,
* with an eventual {@link #refresh()} call activating the context.
*
* <p>In case of multiple configuration files, bean definitions in later files
* will override those defined in earlier files. This can be leveraged to
* deliberately override certain bean definitions via an extra configuration file.
*
* @author Juergen Hoeller
* @author Chris Beams
* @since 3.0
* @see #load
* @see XmlBeanDefinitionReader
* @see org.springframework.context.annotation.AnnotationConfigApplicationContext
*/
public class GenericXmlApplicationContext extends GenericApplicationContext {
private final XmlBeanDefinitionReader reader = new XmlBeanDefinitionReader(this);
/**
* Create a new GenericXmlApplicationContext that needs to be
* {@linkplain #load loaded} and then manually {@link #refresh refreshed}.
*/
public GenericXmlApplicationContext() {
reader.setEnvironment(this.getEnvironment());
}
/**
* Create a new GenericXmlApplicationContext, loading bean definitions
* from the given resources and automatically refreshing the context.
* @param resources the resources to load from
*/
public GenericXmlApplicationContext(Resource... resources) {
load(resources);
refresh();
}
/**
* Create a new GenericXmlApplicationContext, loading bean definitions
* from the given resource locations and automatically refreshing the context.
* @param resourceLocations the resources to load from
*/
public GenericXmlApplicationContext(String... resourceLocations) {
load(resourceLocations);
refresh();
}
/**
* Create a new GenericXmlApplicationContext, loading bean definitions
* from the given resource locations and automatically refreshing the context.
* @param relativeClass class whose package will be used as a prefix when
* loading each specified resource name
* @param resourceNames relatively-qualified names of resources to load
*/
public GenericXmlApplicationContext(Class<?> relativeClass, String... resourceNames) {
load(relativeClass, resourceNames);
refresh();
}
/**
* Set whether to use XML validation. Default is <code>true</code>.
*/
public void setValidating(boolean validating) {
this.reader.setValidating(validating);
}
/**
* {@inheritDoc}
* <p>Delegates the given environment to underlying {@link XmlBeanDefinitionReader}.
* Should be called before any call to {@link #load}.
*/
@Override
public void setEnvironment(ConfigurableEnvironment environment) {
super.setEnvironment(environment);
this.reader.setEnvironment(this.getEnvironment());
}
/**
* Load bean definitions from the given XML resources.
* @param resources one or more resources to load from
*/
public void load(Resource... resources) {
this.reader.loadBeanDefinitions(resources);
}
/**
* Load bean definitions from the given XML resources.
* @param resourceLocations one or more resource locations to load from
*/
public void load(String... resourceLocations) {
this.reader.loadBeanDefinitions(resourceLocations);
}
/**
* Load bean definitions from the given XML resources.
* @param relativeClass class whose package will be used as a prefix when
* loading each specified resource name
* @param resourceNames relatively-qualified names of resources to load
*/
public void load(Class<?> relativeClass, String... resourceNames) {
Resource[] resources = new Resource[resourceNames.length];
for (int i = 0; i < resourceNames.length; i++) {
resources[i] = new ClassPathResource(resourceNames[i], relativeClass);
}
this.load(resources);
}
}

View File

@@ -1,74 +1,74 @@
/*
* Copyright 2002-2009 the original author 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.format.number;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;
import org.springframework.format.Formatter;
/**
* Abstract formatter for Numbers,
* providing a {@link #getNumberFormat(java.util.Locale)} template method.
*
* @author Juergen Hoeller
* @author Keith Donald
* @since 3.0
*/
public abstract class AbstractNumberFormatter implements Formatter<Number> {
private boolean lenient = false;
/**
* Specify whether or not parsing is to be lenient. Default is false.
* <p>With lenient parsing, the parser may allow inputs that do not precisely match the format.
* With strict parsing, inputs must match the format exactly.
*/
public void setLenient(boolean lenient) {
this.lenient = lenient;
}
public String print(Number number, Locale locale) {
return getNumberFormat(locale).format(number);
}
public Number parse(String text, Locale locale) throws ParseException {
NumberFormat format = getNumberFormat(locale);
ParsePosition position = new ParsePosition(0);
Number number = format.parse(text, position);
if (position.getErrorIndex() != -1) {
throw new ParseException(text, position.getIndex());
}
if (!this.lenient) {
if (text.length() != position.getIndex()) {
// indicates a part of the string that was not parsed
throw new ParseException(text, position.getIndex());
}
}
return number;
}
/**
* Obtain a concrete NumberFormat for the specified locale.
* @param locale the current locale
* @return the NumberFormat instance (never <code>null</code>)
*/
protected abstract NumberFormat getNumberFormat(Locale locale);
}
/*
* Copyright 2002-2009 the original author 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.format.number;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.ParsePosition;
import java.util.Locale;
import org.springframework.format.Formatter;
/**
* Abstract formatter for Numbers,
* providing a {@link #getNumberFormat(java.util.Locale)} template method.
*
* @author Juergen Hoeller
* @author Keith Donald
* @since 3.0
*/
public abstract class AbstractNumberFormatter implements Formatter<Number> {
private boolean lenient = false;
/**
* Specify whether or not parsing is to be lenient. Default is false.
* <p>With lenient parsing, the parser may allow inputs that do not precisely match the format.
* With strict parsing, inputs must match the format exactly.
*/
public void setLenient(boolean lenient) {
this.lenient = lenient;
}
public String print(Number number, Locale locale) {
return getNumberFormat(locale).format(number);
}
public Number parse(String text, Locale locale) throws ParseException {
NumberFormat format = getNumberFormat(locale);
ParsePosition position = new ParsePosition(0);
Number number = format.parse(text, position);
if (position.getErrorIndex() != -1) {
throw new ParseException(text, position.getIndex());
}
if (!this.lenient) {
if (text.length() != position.getIndex()) {
// indicates a part of the string that was not parsed
throw new ParseException(text, position.getIndex());
}
}
return number;
}
/**
* Obtain a concrete NumberFormat for the specified locale.
* @param locale the current locale
* @return the NumberFormat instance (never <code>null</code>)
*/
protected abstract NumberFormat getNumberFormat(Locale locale);
}

View File

@@ -1,128 +1,128 @@
/*
* Copyright 2002-2009 the original author 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.instrument.classloading.glassfish;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Reflective wrapper around the GlassFish class loader. Used to
* encapsulate the classloader-specific methods (discovered and
* called through reflection) from the load-time weaver.
*
* <p>Supports GlassFish V1, V2 and V3 (currently in beta).
*
* @author Costin Leau
* @since 3.0
*/
class GlassFishClassLoaderAdapter {
static final String INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V2 = "com.sun.enterprise.loader.InstrumentableClassLoader";
static final String INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V3 = "org.glassfish.api.deployment.InstrumentableClassLoader";
private static final String CLASS_TRANSFORMER = "javax.persistence.spi.ClassTransformer";
private final ClassLoader classLoader;
private final Method addTransformer;
private final Method copy;
private final boolean glassFishV3;
public GlassFishClassLoaderAdapter(ClassLoader classLoader) {
Class<?> instrumentableLoaderClass;
boolean glassV3 = false;
try {
// try the V1/V2 API first
instrumentableLoaderClass = classLoader.loadClass(INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V2);
}
catch (ClassNotFoundException ex) {
// fall back to V3
try {
instrumentableLoaderClass = classLoader.loadClass(INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V3);
glassV3 = true;
}
catch (ClassNotFoundException cnfe) {
throw new IllegalStateException("Could not initialize GlassFish LoadTimeWeaver because " +
"GlassFish (V1, V2 or V3) API classes are not available", ex);
}
}
try {
Class<?> classTransformerClass =
(glassV3 ? ClassFileTransformer.class : classLoader.loadClass(CLASS_TRANSFORMER));
this.addTransformer = instrumentableLoaderClass.getMethod("addTransformer", classTransformerClass);
this.copy = instrumentableLoaderClass.getMethod("copy");
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize GlassFish LoadTimeWeaver because GlassFish API classes are not available", ex);
}
ClassLoader clazzLoader = null;
// Detect transformation-aware ClassLoader by traversing the hierarchy
// (as in GlassFish, Spring can be loaded by the WebappClassLoader).
for (ClassLoader cl = classLoader; cl != null && clazzLoader == null; cl = cl.getParent()) {
if (instrumentableLoaderClass.isInstance(cl)) {
clazzLoader = cl;
}
}
if (clazzLoader == null) {
throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: A [" +
instrumentableLoaderClass.getName() + "] implementation is required.");
}
this.classLoader = clazzLoader;
this.glassFishV3 = glassV3;
}
public void addTransformer(ClassFileTransformer transformer) {
try {
this.addTransformer.invoke(this.classLoader,
(this.glassFishV3 ? transformer : new ClassTransformerAdapter(transformer)));
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("GlassFish addTransformer method threw exception ", ex.getCause());
}
catch (Exception ex) {
throw new IllegalStateException("Could not invoke GlassFish addTransformer method", ex);
}
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public ClassLoader getThrowawayClassLoader() {
try {
return (ClassLoader) this.copy.invoke(this.classLoader);
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("GlassFish copy method threw exception ", ex.getCause());
}
catch (Exception ex) {
throw new IllegalStateException("Could not invoke GlassFish copy method", ex);
}
}
}
/*
* Copyright 2002-2009 the original author 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.instrument.classloading.glassfish;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* Reflective wrapper around the GlassFish class loader. Used to
* encapsulate the classloader-specific methods (discovered and
* called through reflection) from the load-time weaver.
*
* <p>Supports GlassFish V1, V2 and V3 (currently in beta).
*
* @author Costin Leau
* @since 3.0
*/
class GlassFishClassLoaderAdapter {
static final String INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V2 = "com.sun.enterprise.loader.InstrumentableClassLoader";
static final String INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V3 = "org.glassfish.api.deployment.InstrumentableClassLoader";
private static final String CLASS_TRANSFORMER = "javax.persistence.spi.ClassTransformer";
private final ClassLoader classLoader;
private final Method addTransformer;
private final Method copy;
private final boolean glassFishV3;
public GlassFishClassLoaderAdapter(ClassLoader classLoader) {
Class<?> instrumentableLoaderClass;
boolean glassV3 = false;
try {
// try the V1/V2 API first
instrumentableLoaderClass = classLoader.loadClass(INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V2);
}
catch (ClassNotFoundException ex) {
// fall back to V3
try {
instrumentableLoaderClass = classLoader.loadClass(INSTRUMENTABLE_CLASSLOADER_GLASSFISH_V3);
glassV3 = true;
}
catch (ClassNotFoundException cnfe) {
throw new IllegalStateException("Could not initialize GlassFish LoadTimeWeaver because " +
"GlassFish (V1, V2 or V3) API classes are not available", ex);
}
}
try {
Class<?> classTransformerClass =
(glassV3 ? ClassFileTransformer.class : classLoader.loadClass(CLASS_TRANSFORMER));
this.addTransformer = instrumentableLoaderClass.getMethod("addTransformer", classTransformerClass);
this.copy = instrumentableLoaderClass.getMethod("copy");
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize GlassFish LoadTimeWeaver because GlassFish API classes are not available", ex);
}
ClassLoader clazzLoader = null;
// Detect transformation-aware ClassLoader by traversing the hierarchy
// (as in GlassFish, Spring can be loaded by the WebappClassLoader).
for (ClassLoader cl = classLoader; cl != null && clazzLoader == null; cl = cl.getParent()) {
if (instrumentableLoaderClass.isInstance(cl)) {
clazzLoader = cl;
}
}
if (clazzLoader == null) {
throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: A [" +
instrumentableLoaderClass.getName() + "] implementation is required.");
}
this.classLoader = clazzLoader;
this.glassFishV3 = glassV3;
}
public void addTransformer(ClassFileTransformer transformer) {
try {
this.addTransformer.invoke(this.classLoader,
(this.glassFishV3 ? transformer : new ClassTransformerAdapter(transformer)));
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("GlassFish addTransformer method threw exception ", ex.getCause());
}
catch (Exception ex) {
throw new IllegalStateException("Could not invoke GlassFish addTransformer method", ex);
}
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public ClassLoader getThrowawayClassLoader() {
try {
return (ClassLoader) this.copy.invoke(this.classLoader);
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("GlassFish copy method threw exception ", ex.getCause());
}
catch (Exception ex) {
throw new IllegalStateException("Could not invoke GlassFish copy method", ex);
}
}
}

View File

@@ -1,33 +1,33 @@
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
/**
* Simple interface used for handling the different JBoss class loader adapters.
*
* @author Costin Leau
* @since 3.1
*/
interface JBossClassLoaderAdapter {
void addTransformer(ClassFileTransformer transformer);
ClassLoader getInstrumentableClassLoader();
}
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
/**
* Simple interface used for handling the different JBoss class loader adapters.
*
* @author Costin Leau
* @since 3.1
*/
interface JBossClassLoaderAdapter {
void addTransformer(ClassFileTransformer transformer);
ClassLoader getInstrumentableClassLoader();
}

View File

@@ -1,91 +1,91 @@
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.instrument.classloading.SimpleThrowawayClassLoader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@link LoadTimeWeaver} implementation for JBoss's instrumentable ClassLoader.
* Autodetects the specific JBoss version at runtime: currently supports
* JBoss AS 5, 6 and 7 (as of Spring 3.1).
*
* <p><b>NOTE:</b> On JBoss 6.0, to avoid the container loading the classes before the
* application actually starts, one needs to add a <tt>WEB-INF/jboss-scanning.xml</tt>
* file to the application archive - with the following content:
* <pre>&lt;scanning xmlns="urn:jboss:scanning:1.0"/&gt;</pre>
*
* <p>Thanks to Ales Justin and Marius Bogoevici for the initial prototype.
*
* @author Costin Leau
* @since 3.0
*/
public class JBossLoadTimeWeaver implements LoadTimeWeaver {
private final JBossClassLoaderAdapter adapter;
/**
* Create a new instance of the {@link JBossLoadTimeWeaver} class using
* the default {@link ClassLoader class loader}.
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
public JBossLoadTimeWeaver() {
this(ClassUtils.getDefaultClassLoader());
}
/**
* Create a new instance of the {@link JBossLoadTimeWeaver} class using
* the supplied {@link ClassLoader}.
* @param classLoader the <code>ClassLoader</code> to delegate to for
* weaving (must not be <code>null</code>)
*/
public JBossLoadTimeWeaver(ClassLoader classLoader) {
Assert.notNull(classLoader, "ClassLoader must not be null");
String loaderClassName = classLoader.getClass().getName();
if (loaderClassName.startsWith("org.jboss.classloader")) {
// JBoss AS 5 or JBoss AS 6
this.adapter = new JBossMCAdapter(classLoader);
}
else if (loaderClassName.startsWith("org.jboss.modules")) {
// JBoss AS 7
this.adapter = new JBossModulesAdapter(classLoader);
}
else {
throw new IllegalArgumentException("Unexpected ClassLoader type: " + loaderClassName);
}
}
public void addTransformer(ClassFileTransformer transformer) {
this.adapter.addTransformer(transformer);
}
public ClassLoader getInstrumentableClassLoader() {
return this.adapter.getInstrumentableClassLoader();
}
public ClassLoader getThrowawayClassLoader() {
return new SimpleThrowawayClassLoader(getInstrumentableClassLoader());
}
}
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.instrument.classloading.SimpleThrowawayClassLoader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@link LoadTimeWeaver} implementation for JBoss's instrumentable ClassLoader.
* Autodetects the specific JBoss version at runtime: currently supports
* JBoss AS 5, 6 and 7 (as of Spring 3.1).
*
* <p><b>NOTE:</b> On JBoss 6.0, to avoid the container loading the classes before the
* application actually starts, one needs to add a <tt>WEB-INF/jboss-scanning.xml</tt>
* file to the application archive - with the following content:
* <pre>&lt;scanning xmlns="urn:jboss:scanning:1.0"/&gt;</pre>
*
* <p>Thanks to Ales Justin and Marius Bogoevici for the initial prototype.
*
* @author Costin Leau
* @since 3.0
*/
public class JBossLoadTimeWeaver implements LoadTimeWeaver {
private final JBossClassLoaderAdapter adapter;
/**
* Create a new instance of the {@link JBossLoadTimeWeaver} class using
* the default {@link ClassLoader class loader}.
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
public JBossLoadTimeWeaver() {
this(ClassUtils.getDefaultClassLoader());
}
/**
* Create a new instance of the {@link JBossLoadTimeWeaver} class using
* the supplied {@link ClassLoader}.
* @param classLoader the <code>ClassLoader</code> to delegate to for
* weaving (must not be <code>null</code>)
*/
public JBossLoadTimeWeaver(ClassLoader classLoader) {
Assert.notNull(classLoader, "ClassLoader must not be null");
String loaderClassName = classLoader.getClass().getName();
if (loaderClassName.startsWith("org.jboss.classloader")) {
// JBoss AS 5 or JBoss AS 6
this.adapter = new JBossMCAdapter(classLoader);
}
else if (loaderClassName.startsWith("org.jboss.modules")) {
// JBoss AS 7
this.adapter = new JBossModulesAdapter(classLoader);
}
else {
throw new IllegalArgumentException("Unexpected ClassLoader type: " + loaderClassName);
}
}
public void addTransformer(ClassFileTransformer transformer) {
this.adapter.addTransformer(transformer);
}
public ClassLoader getInstrumentableClassLoader() {
return this.adapter.getInstrumentableClassLoader();
}
public ClassLoader getThrowawayClassLoader() {
return new SimpleThrowawayClassLoader(getInstrumentableClassLoader());
}
}

View File

@@ -1,145 +1,145 @@
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Reflective wrapper around a JBoss 5 and 6 class loader methods (discovered and called
* through reflection) for load time weaving.
*
* @author Costin Leau
* @since 3.1
*/
class JBossMCAdapter implements JBossClassLoaderAdapter {
private static final String TRANSLATOR_NAME = "org.jboss.util.loading.Translator";
private static final String POLICY_NAME = "org.jboss.classloader.spi.base.BaseClassLoaderPolicy";
private static final String DOMAIN_NAME = "org.jboss.classloader.spi.base.BaseClassLoaderDomain";
private static final String DEDICATED_SYSTEM = "org.jboss.classloader.spi.ClassLoaderSystem";
private static final String LOADER_NAME = "org.jboss.classloader.spi.base.BaseClassLoader";
private static final String GET_POLICY = "getPolicy";
private static final String GET_DOMAIN = "getClassLoaderDomain";
private static final String GET_SYSTEM = "getClassLoaderSystem";
// available since JBoss AS 5.1.0 / MC 2.0.6 (allows multiple transformers to be added)
private static final String ADD_TRANSLATOR_NAME = "addTranslator";
// available since JBoss AS 5.0.0 / MC 2.0.1 (allows only one transformer to be added)
private static final String SET_TRANSLATOR_NAME = "setTranslator";
private final ClassLoader classLoader;
private final Class<?> translatorClass;
private final Method addTranslator;
private final Object target;
JBossMCAdapter(ClassLoader classLoader) {
Class<?> clazzLoaderType = null;
try {
// resolve BaseClassLoader.class
clazzLoaderType = classLoader.loadClass(LOADER_NAME);
ClassLoader clazzLoader = null;
// walk the hierarchy to detect the instrumentation aware classloader
for (ClassLoader cl = classLoader; cl != null && clazzLoader == null; cl = cl.getParent()) {
if (clazzLoaderType.isInstance(cl)) {
clazzLoader = cl;
}
}
if (clazzLoader == null) {
throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: "
+ "A [" + LOADER_NAME + "] implementation is required.");
}
this.classLoader = clazzLoader;
// use the classloader that loaded the classloader to load
// the types for reflection purposes
classLoader = clazzLoader.getClass().getClassLoader();
// BaseClassLoader#getPolicy
Method method = clazzLoaderType.getDeclaredMethod(GET_POLICY);
ReflectionUtils.makeAccessible(method);
Object policy = method.invoke(this.classLoader);
Object addTarget = null;
Method addMethod = null;
// try the 5.1.x hooks
// check existence of BaseClassLoaderPolicy#addTranslator(Translator)
this.translatorClass = classLoader.loadClass(TRANSLATOR_NAME);
Class<?> clazz = classLoader.loadClass(POLICY_NAME);
try {
addMethod = clazz.getDeclaredMethod(ADD_TRANSLATOR_NAME, translatorClass);
addTarget = policy;
} catch (NoSuchMethodException ex) {
}
// fall back to 5.0.x method
if (addMethod == null) {
// BaseClassLoaderPolicy#getClassLoaderDomain
method = clazz.getDeclaredMethod(GET_DOMAIN);
ReflectionUtils.makeAccessible(method);
Object domain = method.invoke(policy);
// BaseClassLoaderDomain#getClassLoaderSystem
clazz = classLoader.loadClass(DOMAIN_NAME);
method = clazz.getDeclaredMethod(GET_SYSTEM);
ReflectionUtils.makeAccessible(method);
Object system = method.invoke(domain);
// resolve ClassLoaderSystem
clazz = classLoader.loadClass(DEDICATED_SYSTEM);
Assert.isInstanceOf(clazz, system, "JBoss LoadTimeWeaver requires JBoss loader system of type "
+ clazz.getName() + " on JBoss 5.0.x");
// ClassLoaderSystem#setTranslator
addMethod = clazz.getDeclaredMethod(SET_TRANSLATOR_NAME, translatorClass);
addTarget = system;
}
this.addTranslator = addMethod;
this.target = addTarget;
} catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize JBoss LoadTimeWeaver because the JBoss 5 API classes are not available", ex);
}
}
public void addTransformer(ClassFileTransformer transformer) {
InvocationHandler adapter = new JBossMCTranslatorAdapter(transformer);
Object adapterInstance = Proxy.newProxyInstance(this.translatorClass.getClassLoader(),
new Class[] { this.translatorClass }, adapter);
try {
addTranslator.invoke(target, adapterInstance);
} catch (Exception ex) {
throw new IllegalStateException("Could not add transformer on JBoss 5/6 classloader " + classLoader, ex);
}
}
public ClassLoader getInstrumentableClassLoader() {
return classLoader;
}
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Reflective wrapper around a JBoss 5 and 6 class loader methods (discovered and called
* through reflection) for load time weaving.
*
* @author Costin Leau
* @since 3.1
*/
class JBossMCAdapter implements JBossClassLoaderAdapter {
private static final String TRANSLATOR_NAME = "org.jboss.util.loading.Translator";
private static final String POLICY_NAME = "org.jboss.classloader.spi.base.BaseClassLoaderPolicy";
private static final String DOMAIN_NAME = "org.jboss.classloader.spi.base.BaseClassLoaderDomain";
private static final String DEDICATED_SYSTEM = "org.jboss.classloader.spi.ClassLoaderSystem";
private static final String LOADER_NAME = "org.jboss.classloader.spi.base.BaseClassLoader";
private static final String GET_POLICY = "getPolicy";
private static final String GET_DOMAIN = "getClassLoaderDomain";
private static final String GET_SYSTEM = "getClassLoaderSystem";
// available since JBoss AS 5.1.0 / MC 2.0.6 (allows multiple transformers to be added)
private static final String ADD_TRANSLATOR_NAME = "addTranslator";
// available since JBoss AS 5.0.0 / MC 2.0.1 (allows only one transformer to be added)
private static final String SET_TRANSLATOR_NAME = "setTranslator";
private final ClassLoader classLoader;
private final Class<?> translatorClass;
private final Method addTranslator;
private final Object target;
JBossMCAdapter(ClassLoader classLoader) {
Class<?> clazzLoaderType = null;
try {
// resolve BaseClassLoader.class
clazzLoaderType = classLoader.loadClass(LOADER_NAME);
ClassLoader clazzLoader = null;
// walk the hierarchy to detect the instrumentation aware classloader
for (ClassLoader cl = classLoader; cl != null && clazzLoader == null; cl = cl.getParent()) {
if (clazzLoaderType.isInstance(cl)) {
clazzLoader = cl;
}
}
if (clazzLoader == null) {
throw new IllegalArgumentException(classLoader + " and its parents are not suitable ClassLoaders: "
+ "A [" + LOADER_NAME + "] implementation is required.");
}
this.classLoader = clazzLoader;
// use the classloader that loaded the classloader to load
// the types for reflection purposes
classLoader = clazzLoader.getClass().getClassLoader();
// BaseClassLoader#getPolicy
Method method = clazzLoaderType.getDeclaredMethod(GET_POLICY);
ReflectionUtils.makeAccessible(method);
Object policy = method.invoke(this.classLoader);
Object addTarget = null;
Method addMethod = null;
// try the 5.1.x hooks
// check existence of BaseClassLoaderPolicy#addTranslator(Translator)
this.translatorClass = classLoader.loadClass(TRANSLATOR_NAME);
Class<?> clazz = classLoader.loadClass(POLICY_NAME);
try {
addMethod = clazz.getDeclaredMethod(ADD_TRANSLATOR_NAME, translatorClass);
addTarget = policy;
} catch (NoSuchMethodException ex) {
}
// fall back to 5.0.x method
if (addMethod == null) {
// BaseClassLoaderPolicy#getClassLoaderDomain
method = clazz.getDeclaredMethod(GET_DOMAIN);
ReflectionUtils.makeAccessible(method);
Object domain = method.invoke(policy);
// BaseClassLoaderDomain#getClassLoaderSystem
clazz = classLoader.loadClass(DOMAIN_NAME);
method = clazz.getDeclaredMethod(GET_SYSTEM);
ReflectionUtils.makeAccessible(method);
Object system = method.invoke(domain);
// resolve ClassLoaderSystem
clazz = classLoader.loadClass(DEDICATED_SYSTEM);
Assert.isInstanceOf(clazz, system, "JBoss LoadTimeWeaver requires JBoss loader system of type "
+ clazz.getName() + " on JBoss 5.0.x");
// ClassLoaderSystem#setTranslator
addMethod = clazz.getDeclaredMethod(SET_TRANSLATOR_NAME, translatorClass);
addTarget = system;
}
this.addTranslator = addMethod;
this.target = addTarget;
} catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize JBoss LoadTimeWeaver because the JBoss 5 API classes are not available", ex);
}
}
public void addTransformer(ClassFileTransformer transformer) {
InvocationHandler adapter = new JBossMCTranslatorAdapter(transformer);
Object adapterInstance = Proxy.newProxyInstance(this.translatorClass.getClassLoader(),
new Class[] { this.translatorClass }, adapter);
try {
addTranslator.invoke(target, adapterInstance);
} catch (Exception ex) {
throw new IllegalStateException("Could not add transformer on JBoss 5/6 classloader " + classLoader, ex);
}
}
public ClassLoader getInstrumentableClassLoader() {
return classLoader;
}
}

View File

@@ -1,82 +1,82 @@
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
/**
* Adapter that implements JBoss Translator interface, delegating to a
* standard JDK {@link ClassFileTransformer} underneath.
*
* <p>To avoid compile time checks again the vendor API, a dynamic proxy is
* being used.
*
* @author Costin Leau
* @since 3.1
*/
class JBossMCTranslatorAdapter implements InvocationHandler {
private final ClassFileTransformer transformer;
/**
* Creates a new {@link JBossMCTranslatorAdapter}.
* @param transformer the {@link ClassFileTransformer} to be adapted (must
* not be <code>null</code>)
*/
public JBossMCTranslatorAdapter(ClassFileTransformer transformer) {
this.transformer = transformer;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if ("equals".equals(name)) {
return (Boolean.valueOf(proxy == args[0]));
} else if ("hashCode".equals(name)) {
return hashCode();
} else if ("toString".equals(name)) {
return toString();
} else if ("transform".equals(name)) {
return transform((ClassLoader) args[0], (String) args[1], (Class<?>) args[2], (ProtectionDomain) args[3],
(byte[]) args[4]);
} else if ("unregisterClassLoader".equals(name)) {
unregisterClassLoader((ClassLoader) args[0]);
return null;
} else {
throw new IllegalArgumentException("Unknown method: " + method);
}
}
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws Exception {
return transformer.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
}
public void unregisterClassLoader(ClassLoader loader) {
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getName());
builder.append(" for transformer: ");
builder.append(this.transformer);
return builder.toString();
}
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
/**
* Adapter that implements JBoss Translator interface, delegating to a
* standard JDK {@link ClassFileTransformer} underneath.
*
* <p>To avoid compile time checks again the vendor API, a dynamic proxy is
* being used.
*
* @author Costin Leau
* @since 3.1
*/
class JBossMCTranslatorAdapter implements InvocationHandler {
private final ClassFileTransformer transformer;
/**
* Creates a new {@link JBossMCTranslatorAdapter}.
* @param transformer the {@link ClassFileTransformer} to be adapted (must
* not be <code>null</code>)
*/
public JBossMCTranslatorAdapter(ClassFileTransformer transformer) {
this.transformer = transformer;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if ("equals".equals(name)) {
return (Boolean.valueOf(proxy == args[0]));
} else if ("hashCode".equals(name)) {
return hashCode();
} else if ("toString".equals(name)) {
return toString();
} else if ("transform".equals(name)) {
return transform((ClassLoader) args[0], (String) args[1], (Class<?>) args[2], (ProtectionDomain) args[3],
(byte[]) args[4]);
} else if ("unregisterClassLoader".equals(name)) {
unregisterClassLoader((ClassLoader) args[0]);
return null;
} else {
throw new IllegalArgumentException("Unknown method: " + method);
}
}
public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
ProtectionDomain protectionDomain, byte[] classfileBuffer) throws Exception {
return transformer.transform(loader, className, classBeingRedefined, protectionDomain, classfileBuffer);
}
public void unregisterClassLoader(ClassLoader loader) {
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getName());
builder.append(" for transformer: ");
builder.append(this.transformer);
return builder.toString();
}
}

View File

@@ -1,71 +1,71 @@
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* JBoss 7 adapter.
*
* @author Costin Leau
* @since 3.1
*/
class JBossModulesAdapter implements JBossClassLoaderAdapter {
private static final String TRANSFORMER_FIELD_NAME = "transformer";
private static final String TRANSFORMER_ADD_METHOD_NAME = "addTransformer";
private static final String DELEGATING_TRANSFORMER_CLASS_NAME = "org.jboss.as.server.deployment.module.DelegatingClassFileTransformer";
private final ClassLoader classLoader;
private final Method addTransformer;
private final Object delegatingTransformer;
public JBossModulesAdapter(ClassLoader loader) {
this.classLoader = loader;
try {
Field transformers = ReflectionUtils.findField(classLoader.getClass(), TRANSFORMER_FIELD_NAME);
transformers.setAccessible(true);
delegatingTransformer = transformers.get(classLoader);
Assert.state(delegatingTransformer.getClass().getName().equals(DELEGATING_TRANSFORMER_CLASS_NAME),
"Transformer not of the expected type: " + delegatingTransformer.getClass().getName());
addTransformer = ReflectionUtils.findMethod(delegatingTransformer.getClass(), TRANSFORMER_ADD_METHOD_NAME,
ClassFileTransformer.class);
addTransformer.setAccessible(true);
} catch (Exception ex) {
throw new IllegalStateException("Could not initialize JBoss 7 LoadTimeWeaver", ex);
}
}
public void addTransformer(ClassFileTransformer transformer) {
try {
addTransformer.invoke(delegatingTransformer, transformer);
} catch (Exception ex) {
throw new IllegalStateException("Could not add transformer on JBoss 7 classloader " + classLoader, ex);
}
}
public ClassLoader getInstrumentableClassLoader() {
return classLoader;
}
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.jboss;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* JBoss 7 adapter.
*
* @author Costin Leau
* @since 3.1
*/
class JBossModulesAdapter implements JBossClassLoaderAdapter {
private static final String TRANSFORMER_FIELD_NAME = "transformer";
private static final String TRANSFORMER_ADD_METHOD_NAME = "addTransformer";
private static final String DELEGATING_TRANSFORMER_CLASS_NAME = "org.jboss.as.server.deployment.module.DelegatingClassFileTransformer";
private final ClassLoader classLoader;
private final Method addTransformer;
private final Object delegatingTransformer;
public JBossModulesAdapter(ClassLoader loader) {
this.classLoader = loader;
try {
Field transformers = ReflectionUtils.findField(classLoader.getClass(), TRANSFORMER_FIELD_NAME);
transformers.setAccessible(true);
delegatingTransformer = transformers.get(classLoader);
Assert.state(delegatingTransformer.getClass().getName().equals(DELEGATING_TRANSFORMER_CLASS_NAME),
"Transformer not of the expected type: " + delegatingTransformer.getClass().getName());
addTransformer = ReflectionUtils.findMethod(delegatingTransformer.getClass(), TRANSFORMER_ADD_METHOD_NAME,
ClassFileTransformer.class);
addTransformer.setAccessible(true);
} catch (Exception ex) {
throw new IllegalStateException("Could not initialize JBoss 7 LoadTimeWeaver", ex);
}
}
public void addTransformer(ClassFileTransformer transformer) {
try {
addTransformer.invoke(delegatingTransformer, transformer);
} catch (Exception ex) {
throw new IllegalStateException("Could not add transformer on JBoss 7 classloader " + classLoader, ex);
}
}
public ClassLoader getInstrumentableClassLoader() {
return classLoader;
}
}

View File

@@ -1,8 +1,8 @@
/**
*
* Support for class instrumentation on JBoss AS 5.x / JBoss MC 2.0.x.
*
*/
package org.springframework.instrument.classloading.jboss;
/**
*
* Support for class instrumentation on JBoss AS 5.x / JBoss MC 2.0.x.
*
*/
package org.springframework.instrument.classloading.jboss;

View File

@@ -1,88 +1,88 @@
/*
* Copyright 2006-2009 the original author 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.instrument.classloading.oc4j;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.util.Assert;
/**
* Reflective wrapper around a OC4J class loader. Used to
* encapsulate the classloader-specific methods (discovered and
* called through reflection) from the load-time weaver.
*
* @author Costin Leau
*/
class OC4JClassLoaderAdapter {
private static final String CL_UTILS = "oracle.classloader.util.ClassLoaderUtilities";
private static final String PREPROCESS_UTILS = "oracle.classloader.util.ClassPreprocessor";
private final ClassLoader classLoader;
private final Class<?> processorClass;
private final Method addTransformer;
private final Method copy;
public OC4JClassLoaderAdapter(ClassLoader classLoader) {
try {
// Since OC4J 10.1.3's PolicyClassLoader is going to be removed,
// we rely on the ClassLoaderUtilities API instead.
Class<?> utilClass = classLoader.loadClass(CL_UTILS);
this.processorClass = classLoader.loadClass(PREPROCESS_UTILS);
this.addTransformer = utilClass.getMethod("addPreprocessor", new Class[] { ClassLoader.class,
this.processorClass });
this.copy = utilClass.getMethod("copy", new Class[] { ClassLoader.class });
} catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize OC4J LoadTimeWeaver because OC4J API classes are not available", ex);
}
this.classLoader = classLoader;
}
public void addTransformer(ClassFileTransformer transformer) {
Assert.notNull(transformer, "ClassFileTransformer must not be null");
try {
OC4JClassPreprocessorAdapter adapter = new OC4JClassPreprocessorAdapter(transformer);
Object adapterInstance = Proxy.newProxyInstance(this.processorClass.getClassLoader(),
new Class[] { this.processorClass }, adapter);
this.addTransformer.invoke(null, new Object[] { this.classLoader, adapterInstance });
} catch (InvocationTargetException ex) {
throw new IllegalStateException("OC4J addPreprocessor method threw exception", ex.getCause());
} catch (Exception ex) {
throw new IllegalStateException("Could not invoke OC4J addPreprocessor method", ex);
}
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public ClassLoader getThrowawayClassLoader() {
try {
return (ClassLoader) this.copy.invoke(null, new Object[] { this.classLoader });
} catch (InvocationTargetException ex) {
throw new IllegalStateException("OC4J copy method failed", ex.getCause());
} catch (Exception ex) {
throw new IllegalStateException("Could not copy OC4J classloader", ex);
}
}
/*
* Copyright 2006-2009 the original author 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.instrument.classloading.oc4j;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import org.springframework.util.Assert;
/**
* Reflective wrapper around a OC4J class loader. Used to
* encapsulate the classloader-specific methods (discovered and
* called through reflection) from the load-time weaver.
*
* @author Costin Leau
*/
class OC4JClassLoaderAdapter {
private static final String CL_UTILS = "oracle.classloader.util.ClassLoaderUtilities";
private static final String PREPROCESS_UTILS = "oracle.classloader.util.ClassPreprocessor";
private final ClassLoader classLoader;
private final Class<?> processorClass;
private final Method addTransformer;
private final Method copy;
public OC4JClassLoaderAdapter(ClassLoader classLoader) {
try {
// Since OC4J 10.1.3's PolicyClassLoader is going to be removed,
// we rely on the ClassLoaderUtilities API instead.
Class<?> utilClass = classLoader.loadClass(CL_UTILS);
this.processorClass = classLoader.loadClass(PREPROCESS_UTILS);
this.addTransformer = utilClass.getMethod("addPreprocessor", new Class[] { ClassLoader.class,
this.processorClass });
this.copy = utilClass.getMethod("copy", new Class[] { ClassLoader.class });
} catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize OC4J LoadTimeWeaver because OC4J API classes are not available", ex);
}
this.classLoader = classLoader;
}
public void addTransformer(ClassFileTransformer transformer) {
Assert.notNull(transformer, "ClassFileTransformer must not be null");
try {
OC4JClassPreprocessorAdapter adapter = new OC4JClassPreprocessorAdapter(transformer);
Object adapterInstance = Proxy.newProxyInstance(this.processorClass.getClassLoader(),
new Class[] { this.processorClass }, adapter);
this.addTransformer.invoke(null, new Object[] { this.classLoader, adapterInstance });
} catch (InvocationTargetException ex) {
throw new IllegalStateException("OC4J addPreprocessor method threw exception", ex.getCause());
} catch (Exception ex) {
throw new IllegalStateException("Could not invoke OC4J addPreprocessor method", ex);
}
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public ClassLoader getThrowawayClassLoader() {
try {
return (ClassLoader) this.copy.invoke(null, new Object[] { this.classLoader });
} catch (InvocationTargetException ex) {
throw new IllegalStateException("OC4J copy method failed", ex.getCause());
} catch (Exception ex) {
throw new IllegalStateException("Could not copy OC4J classloader", ex);
}
}
}

View File

@@ -1,95 +1,95 @@
/*
* Copyright 2006-2009 the original author 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.instrument.classloading.oc4j;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
/**
* Adapter that implements OC4J ClassPreProcessor interface, delegating to a
* standard JDK {@link ClassFileTransformer} underneath.
*
* <p>To avoid compile time checks again the vendor API, a dynamic proxy is
* being used.
*
* @author Costin Leau
*/
class OC4JClassPreprocessorAdapter implements InvocationHandler {
private final ClassFileTransformer transformer;
/**
* Creates a new {@link OC4JClassPreprocessorAdapter}.
* @param transformer the {@link ClassFileTransformer} to be adapted (must
* not be <code>null</code>)
*/
public OC4JClassPreprocessorAdapter(ClassFileTransformer transformer) {
this.transformer = transformer;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if ("equals".equals(name)) {
return (Boolean.valueOf(proxy == args[0]));
} else if ("hashCode".equals(name)) {
return hashCode();
} else if ("toString".equals(name)) {
return toString();
} else if ("initialize".equals(name)) {
initialize(proxy, (ClassLoader) args[0]);
return null;
} else if ("processClass".equals(name)) {
return processClass((String) args[0], (byte[]) args[1], (Integer) args[2], (Integer) args[3],
(ProtectionDomain) args[4], (ClassLoader) args[5]);
} else {
throw new IllegalArgumentException("Unknown method: " + method);
}
}
// maps to oracle.classloader.util.ClassPreprocessor#initialize
// the proxy is passed since it implements the Oracle interface which
// is asked as a return type
public Object initialize(Object proxy, ClassLoader loader) {
return proxy;
}
public byte[] processClass(String className, byte origClassBytes[], int offset, int length, ProtectionDomain pd,
ClassLoader loader) {
try {
byte[] tempArray = new byte[length];
System.arraycopy(origClassBytes, offset, tempArray, 0, length);
// NB: OC4J passes className as "." without class while the
// transformer expects a VM, "/" format
byte[] result = this.transformer.transform(loader, className.replace('.', '/'), null, pd, tempArray);
return (result != null ? result : origClassBytes);
} catch (IllegalClassFormatException ex) {
throw new IllegalStateException("Cannot transform because of illegal class format", ex);
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getName());
builder.append(" for transformer: ");
builder.append(this.transformer);
return builder.toString();
}
/*
* Copyright 2006-2009 the original author 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.instrument.classloading.oc4j;
import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.security.ProtectionDomain;
/**
* Adapter that implements OC4J ClassPreProcessor interface, delegating to a
* standard JDK {@link ClassFileTransformer} underneath.
*
* <p>To avoid compile time checks again the vendor API, a dynamic proxy is
* being used.
*
* @author Costin Leau
*/
class OC4JClassPreprocessorAdapter implements InvocationHandler {
private final ClassFileTransformer transformer;
/**
* Creates a new {@link OC4JClassPreprocessorAdapter}.
* @param transformer the {@link ClassFileTransformer} to be adapted (must
* not be <code>null</code>)
*/
public OC4JClassPreprocessorAdapter(ClassFileTransformer transformer) {
this.transformer = transformer;
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if ("equals".equals(name)) {
return (Boolean.valueOf(proxy == args[0]));
} else if ("hashCode".equals(name)) {
return hashCode();
} else if ("toString".equals(name)) {
return toString();
} else if ("initialize".equals(name)) {
initialize(proxy, (ClassLoader) args[0]);
return null;
} else if ("processClass".equals(name)) {
return processClass((String) args[0], (byte[]) args[1], (Integer) args[2], (Integer) args[3],
(ProtectionDomain) args[4], (ClassLoader) args[5]);
} else {
throw new IllegalArgumentException("Unknown method: " + method);
}
}
// maps to oracle.classloader.util.ClassPreprocessor#initialize
// the proxy is passed since it implements the Oracle interface which
// is asked as a return type
public Object initialize(Object proxy, ClassLoader loader) {
return proxy;
}
public byte[] processClass(String className, byte origClassBytes[], int offset, int length, ProtectionDomain pd,
ClassLoader loader) {
try {
byte[] tempArray = new byte[length];
System.arraycopy(origClassBytes, offset, tempArray, 0, length);
// NB: OC4J passes className as "." without class while the
// transformer expects a VM, "/" format
byte[] result = this.transformer.transform(loader, className.replace('.', '/'), null, pd, tempArray);
return (result != null ? result : origClassBytes);
} catch (IllegalClassFormatException ex) {
throw new IllegalStateException("Cannot transform because of illegal class format", ex);
}
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getName());
builder.append(" for transformer: ");
builder.append(this.transformer);
return builder.toString();
}
}

View File

@@ -1,111 +1,111 @@
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.websphere;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import org.springframework.util.Assert;
/**
*
* Reflective wrapper around a WebSphere 7 class loader. Used to
* encapsulate the classloader-specific methods (discovered and
* called through reflection) from the load-time weaver.
*
* @author Costin Leau
* @since 3.1
*/
class WebSphereClassLoaderAdapter {
private static final String COMPOUND_CLASS_LOADER_NAME = "com.ibm.ws.classloader.CompoundClassLoader";
private static final String CLASS_PRE_PROCESSOR_NAME = "com.ibm.websphere.classloader.ClassLoaderInstancePreDefinePlugin";
private static final String PLUGINS_FIELD = "preDefinePlugins";
private ClassLoader classLoader;
private Class<?> wsPreProcessorClass;
private Method addPreDefinePlugin;
private Constructor<? extends ClassLoader> cloneConstructor;
private Field transformerList;
public WebSphereClassLoaderAdapter(ClassLoader classLoader) {
Class<?> wsCompoundClassLoaderClass = null;
try {
wsCompoundClassLoaderClass = classLoader.loadClass(COMPOUND_CLASS_LOADER_NAME);
cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
cloneConstructor.setAccessible(true);
wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", wsPreProcessorClass);
transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
transformerList.setAccessible(true);
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize WebSphere LoadTimeWeaver because WebSphere 7 API classes are not available",
ex);
}
Assert.isInstanceOf(wsCompoundClassLoaderClass, classLoader,
"ClassLoader must be instance of [" + COMPOUND_CLASS_LOADER_NAME + "]");
this.classLoader = classLoader;
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public void addTransformer(ClassFileTransformer transformer) {
Assert.notNull(transformer, "ClassFileTransformer must not be null");
try {
InvocationHandler adapter = new WebSphereClassPreDefinePlugin(transformer);
Object adapterInstance = Proxy.newProxyInstance(this.wsPreProcessorClass.getClassLoader(),
new Class[] { this.wsPreProcessorClass }, adapter);
this.addPreDefinePlugin.invoke(this.classLoader, adapterInstance);
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebSphere addPreDefinePlugin method threw exception", ex.getCause());
}
catch (Exception ex) {
throw new IllegalStateException("Could not invoke WebSphere addPreDefinePlugin method", ex);
}
}
@SuppressWarnings("unchecked")
public ClassLoader getThrowawayClassLoader() {
try {
ClassLoader loader = (ClassLoader) cloneConstructor.newInstance(getClassLoader());
// clear out the transformers (copied as well)
List list = (List) transformerList.get(loader);
list.clear();
return loader;
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebSphere CompoundClassLoader constructor failed", ex.getCause());
}
catch (Exception ex) {
throw new IllegalStateException("Could not construct WebSphere CompoundClassLoader", ex);
}
}
}
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.websphere;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.List;
import org.springframework.util.Assert;
/**
*
* Reflective wrapper around a WebSphere 7 class loader. Used to
* encapsulate the classloader-specific methods (discovered and
* called through reflection) from the load-time weaver.
*
* @author Costin Leau
* @since 3.1
*/
class WebSphereClassLoaderAdapter {
private static final String COMPOUND_CLASS_LOADER_NAME = "com.ibm.ws.classloader.CompoundClassLoader";
private static final String CLASS_PRE_PROCESSOR_NAME = "com.ibm.websphere.classloader.ClassLoaderInstancePreDefinePlugin";
private static final String PLUGINS_FIELD = "preDefinePlugins";
private ClassLoader classLoader;
private Class<?> wsPreProcessorClass;
private Method addPreDefinePlugin;
private Constructor<? extends ClassLoader> cloneConstructor;
private Field transformerList;
public WebSphereClassLoaderAdapter(ClassLoader classLoader) {
Class<?> wsCompoundClassLoaderClass = null;
try {
wsCompoundClassLoaderClass = classLoader.loadClass(COMPOUND_CLASS_LOADER_NAME);
cloneConstructor = classLoader.getClass().getDeclaredConstructor(wsCompoundClassLoaderClass);
cloneConstructor.setAccessible(true);
wsPreProcessorClass = classLoader.loadClass(CLASS_PRE_PROCESSOR_NAME);
addPreDefinePlugin = classLoader.getClass().getMethod("addPreDefinePlugin", wsPreProcessorClass);
transformerList = wsCompoundClassLoaderClass.getDeclaredField(PLUGINS_FIELD);
transformerList.setAccessible(true);
}
catch (Exception ex) {
throw new IllegalStateException(
"Could not initialize WebSphere LoadTimeWeaver because WebSphere 7 API classes are not available",
ex);
}
Assert.isInstanceOf(wsCompoundClassLoaderClass, classLoader,
"ClassLoader must be instance of [" + COMPOUND_CLASS_LOADER_NAME + "]");
this.classLoader = classLoader;
}
public ClassLoader getClassLoader() {
return this.classLoader;
}
public void addTransformer(ClassFileTransformer transformer) {
Assert.notNull(transformer, "ClassFileTransformer must not be null");
try {
InvocationHandler adapter = new WebSphereClassPreDefinePlugin(transformer);
Object adapterInstance = Proxy.newProxyInstance(this.wsPreProcessorClass.getClassLoader(),
new Class[] { this.wsPreProcessorClass }, adapter);
this.addPreDefinePlugin.invoke(this.classLoader, adapterInstance);
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebSphere addPreDefinePlugin method threw exception", ex.getCause());
}
catch (Exception ex) {
throw new IllegalStateException("Could not invoke WebSphere addPreDefinePlugin method", ex);
}
}
@SuppressWarnings("unchecked")
public ClassLoader getThrowawayClassLoader() {
try {
ClassLoader loader = (ClassLoader) cloneConstructor.newInstance(getClassLoader());
// clear out the transformers (copied as well)
List list = (List) transformerList.get(loader);
list.clear();
return loader;
}
catch (InvocationTargetException ex) {
throw new IllegalStateException("WebSphere CompoundClassLoader constructor failed", ex.getCause());
}
catch (Exception ex) {
throw new IllegalStateException("Could not construct WebSphere CompoundClassLoader", ex);
}
}
}

View File

@@ -1,100 +1,100 @@
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.websphere;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.security.CodeSource;
import org.springframework.util.FileCopyUtils;
/**
* Adapter that implements WebSphere 7.0 ClassPreProcessPlugin interface,
* delegating to a standard JDK {@link ClassFileTransformer} underneath.
*
* <p>To avoid compile time checks again the vendor API, a dynamic proxy is
* being used.
*
* @author Costin Leau
* @since 3.1
*/
class WebSphereClassPreDefinePlugin implements InvocationHandler {
private final ClassFileTransformer transformer;
/**
* Create a new {@link WebSphereClassPreDefinePlugin}.
* @param transformer the {@link ClassFileTransformer} to be adapted
* (must not be <code>null</code>)
*/
public WebSphereClassPreDefinePlugin(ClassFileTransformer transformer) {
this.transformer = transformer;
ClassLoader classLoader = transformer.getClass().getClassLoader();
// first force the full class loading of the weaver by invoking transformation on a dummy class
try {
String dummyClass = Dummy.class.getName().replace('.', '/');
byte[] bytes = FileCopyUtils.copyToByteArray(classLoader.getResourceAsStream(dummyClass + ".class"));
transformer.transform(classLoader, dummyClass, null, null, bytes);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot load transformer", ex);
}
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if ("equals".equals(name)) {
return (proxy == args[0]);
}
else if ("hashCode".equals(name)) {
return hashCode();
}
else if ("toString".equals(name)) {
return toString();
}
else if ("transformClass".equals(name)) {
return transform((String) args[0], (byte[]) args[1], (CodeSource) args[2], (ClassLoader) args[3]);
}
else {
throw new IllegalArgumentException("Unknown method: " + method);
}
}
protected byte[] transform(String className, byte[] classfileBuffer, CodeSource codeSource, ClassLoader classLoader)
throws Exception {
// NB: WebSphere passes className as "." without class while the transformer expects a VM, "/" format
byte[] result = transformer.transform(classLoader, className.replace('.', '/'), null, null, classfileBuffer);
return (result != null ? result : classfileBuffer);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getName());
builder.append(" for transformer: ");
builder.append(this.transformer);
return builder.toString();
}
private static class Dummy {
}
}
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.websphere;
import java.lang.instrument.ClassFileTransformer;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.security.CodeSource;
import org.springframework.util.FileCopyUtils;
/**
* Adapter that implements WebSphere 7.0 ClassPreProcessPlugin interface,
* delegating to a standard JDK {@link ClassFileTransformer} underneath.
*
* <p>To avoid compile time checks again the vendor API, a dynamic proxy is
* being used.
*
* @author Costin Leau
* @since 3.1
*/
class WebSphereClassPreDefinePlugin implements InvocationHandler {
private final ClassFileTransformer transformer;
/**
* Create a new {@link WebSphereClassPreDefinePlugin}.
* @param transformer the {@link ClassFileTransformer} to be adapted
* (must not be <code>null</code>)
*/
public WebSphereClassPreDefinePlugin(ClassFileTransformer transformer) {
this.transformer = transformer;
ClassLoader classLoader = transformer.getClass().getClassLoader();
// first force the full class loading of the weaver by invoking transformation on a dummy class
try {
String dummyClass = Dummy.class.getName().replace('.', '/');
byte[] bytes = FileCopyUtils.copyToByteArray(classLoader.getResourceAsStream(dummyClass + ".class"));
transformer.transform(classLoader, dummyClass, null, null, bytes);
}
catch (Throwable ex) {
throw new IllegalArgumentException("Cannot load transformer", ex);
}
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
String name = method.getName();
if ("equals".equals(name)) {
return (proxy == args[0]);
}
else if ("hashCode".equals(name)) {
return hashCode();
}
else if ("toString".equals(name)) {
return toString();
}
else if ("transformClass".equals(name)) {
return transform((String) args[0], (byte[]) args[1], (CodeSource) args[2], (ClassLoader) args[3]);
}
else {
throw new IllegalArgumentException("Unknown method: " + method);
}
}
protected byte[] transform(String className, byte[] classfileBuffer, CodeSource codeSource, ClassLoader classLoader)
throws Exception {
// NB: WebSphere passes className as "." without class while the transformer expects a VM, "/" format
byte[] result = transformer.transform(classLoader, className.replace('.', '/'), null, null, classfileBuffer);
return (result != null ? result : classfileBuffer);
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(getClass().getName());
builder.append(" for transformer: ");
builder.append(this.transformer);
return builder.toString();
}
private static class Dummy {
}
}

View File

@@ -1,70 +1,70 @@
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.websphere;
import java.lang.instrument.ClassFileTransformer;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@link LoadTimeWeaver} implementation for WebSphere's instrumentable ClassLoader.
* Compatible with WebSphere 7 as well as 8.
*
* @author Costin Leau
* @since 3.1
*/
public class WebSphereLoadTimeWeaver implements LoadTimeWeaver {
private final WebSphereClassLoaderAdapter classLoader;
/**
* Create a new instance of the {@link WebSphereLoadTimeWeaver} class using
* the default {@link ClassLoader class loader}.
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
public WebSphereLoadTimeWeaver() {
this(ClassUtils.getDefaultClassLoader());
}
/**
* Create a new instance of the {@link WebSphereLoadTimeWeaver} class using
* the supplied {@link ClassLoader}.
* @param classLoader the <code>ClassLoader</code> to delegate to for weaving
* (must not be <code>null</code>)
*/
public WebSphereLoadTimeWeaver(ClassLoader classLoader) {
Assert.notNull(classLoader, "ClassLoader must not be null");
this.classLoader = new WebSphereClassLoaderAdapter(classLoader);
}
public void addTransformer(ClassFileTransformer transformer) {
this.classLoader.addTransformer(transformer);
}
public ClassLoader getInstrumentableClassLoader() {
return this.classLoader.getClassLoader();
}
public ClassLoader getThrowawayClassLoader() {
return this.classLoader.getThrowawayClassLoader();
}
}
/*
* Copyright 2002-2011 the original author 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.instrument.classloading.websphere;
import java.lang.instrument.ClassFileTransformer;
import org.springframework.instrument.classloading.LoadTimeWeaver;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* {@link LoadTimeWeaver} implementation for WebSphere's instrumentable ClassLoader.
* Compatible with WebSphere 7 as well as 8.
*
* @author Costin Leau
* @since 3.1
*/
public class WebSphereLoadTimeWeaver implements LoadTimeWeaver {
private final WebSphereClassLoaderAdapter classLoader;
/**
* Create a new instance of the {@link WebSphereLoadTimeWeaver} class using
* the default {@link ClassLoader class loader}.
* @see org.springframework.util.ClassUtils#getDefaultClassLoader()
*/
public WebSphereLoadTimeWeaver() {
this(ClassUtils.getDefaultClassLoader());
}
/**
* Create a new instance of the {@link WebSphereLoadTimeWeaver} class using
* the supplied {@link ClassLoader}.
* @param classLoader the <code>ClassLoader</code> to delegate to for weaving
* (must not be <code>null</code>)
*/
public WebSphereLoadTimeWeaver(ClassLoader classLoader) {
Assert.notNull(classLoader, "ClassLoader must not be null");
this.classLoader = new WebSphereClassLoaderAdapter(classLoader);
}
public void addTransformer(ClassFileTransformer transformer) {
this.classLoader.addTransformer(transformer);
}
public ClassLoader getInstrumentableClassLoader() {
return this.classLoader.getClassLoader();
}
public ClassLoader getThrowawayClassLoader() {
return this.classLoader.getThrowawayClassLoader();
}
}

View File

@@ -1,8 +1,8 @@
/**
*
* Support for class instrumentation on IBM WebSphere Application Server 7.
*
*/
package org.springframework.instrument.classloading.websphere;
/**
*
* Support for class instrumentation on IBM WebSphere Application Server 7.
*
*/
package org.springframework.instrument.classloading.websphere;

View File

@@ -1,69 +1,69 @@
/*
* Copyright 2002-2011 the original author 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.jndi;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* {@link JndiLocatorSupport} subclass with public lookup methods,
* for convenient use as a delegate.
*
* @author Juergen Hoeller
* @since 3.0.1
*/
public class JndiLocatorDelegate extends JndiLocatorSupport {
@Override
public Object lookup(String jndiName) throws NamingException {
return super.lookup(jndiName);
}
@Override
public <T> T lookup(String jndiName, Class<T> requiredType) throws NamingException {
return super.lookup(jndiName, requiredType);
}
/**
* Configure a {@code JndiLocatorDelegate} with its "resourceRef" property set to
* <code>true</code>, meaning that all names will be prefixed with "java:comp/env/".
* @see #setResourceRef
*/
public static JndiLocatorDelegate createDefaultResourceRefLocator() {
JndiLocatorDelegate jndiLocator = new JndiLocatorDelegate();
jndiLocator.setResourceRef(true);
return jndiLocator;
}
/**
* Check whether a default JNDI environment, as in a J2EE environment,
* is available on this JVM.
* @return <code>true</code> if a default InitialContext can be used,
* <code>false</code> if not
*/
public static boolean isDefaultJndiEnvironmentAvailable() {
try {
new InitialContext();
return true;
}
catch (Throwable ex) {
return false;
}
}
}
/*
* Copyright 2002-2011 the original author 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.jndi;
import javax.naming.InitialContext;
import javax.naming.NamingException;
/**
* {@link JndiLocatorSupport} subclass with public lookup methods,
* for convenient use as a delegate.
*
* @author Juergen Hoeller
* @since 3.0.1
*/
public class JndiLocatorDelegate extends JndiLocatorSupport {
@Override
public Object lookup(String jndiName) throws NamingException {
return super.lookup(jndiName);
}
@Override
public <T> T lookup(String jndiName, Class<T> requiredType) throws NamingException {
return super.lookup(jndiName, requiredType);
}
/**
* Configure a {@code JndiLocatorDelegate} with its "resourceRef" property set to
* <code>true</code>, meaning that all names will be prefixed with "java:comp/env/".
* @see #setResourceRef
*/
public static JndiLocatorDelegate createDefaultResourceRefLocator() {
JndiLocatorDelegate jndiLocator = new JndiLocatorDelegate();
jndiLocator.setResourceRef(true);
return jndiLocator;
}
/**
* Check whether a default JNDI environment, as in a J2EE environment,
* is available on this JVM.
* @return <code>true</code> if a default InitialContext can be used,
* <code>false</code> if not
*/
public static boolean isDefaultJndiEnvironmentAvailable() {
try {
new InitialContext();
return true;
}
catch (Throwable ex) {
return false;
}
}
}

View File

@@ -1,139 +1,139 @@
/*
* Copyright 2002-2010 the original author 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;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
/**
* Task scheduler interface that abstracts the scheduling of
* {@link Runnable Runnables} based on different kinds of triggers.
*
* <p>This interface is separate from {@link SchedulingTaskExecutor} since it
* usually represents for a different kind of backend, i.e. a thread pool with
* different characteristics and capabilities. Implementations may implement
* both interfaces if they can handle both kinds of execution characteristics.
*
* <p>The 'default' implementation is
* {@link org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler},
* wrapping a native {@link java.util.concurrent.ScheduledExecutorService}
* and adding extended trigger capabilities.
*
* <p>This interface is roughly equivalent to a JSR-236
* <code>ManagedScheduledExecutorService</code> as supported in Java EE 6
* environments. However, at the time of the Spring 3.0 release, the
* JSR-236 interfaces have not been released in official form yet.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.core.task.TaskExecutor
* @see java.util.concurrent.ScheduledExecutorService
* @see org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
*/
public interface TaskScheduler {
/**
* Schedule the given {@link Runnable}, invoking it whenever the trigger
* indicates a next execution time.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param trigger an implementation of the {@link Trigger} interface,
* e.g. a {@link org.springframework.scheduling.support.CronTrigger} object
* wrapping a cron expression
* @return a {@link ScheduledFuture} representing pending completion of the task,
* or <code>null</code> if the given Trigger object never fires (i.e. returns
* <code>null</code> from {@link Trigger#nextExecutionTime})
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
* @see org.springframework.scheduling.support.CronTrigger
*/
ScheduledFuture schedule(Runnable task, Trigger trigger);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param startTime the desired execution time for the task
* (if this is in the past, the task will be executed immediately, i.e. as soon as possible)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture schedule(Runnable task, Date startTime);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time
* and subsequently with the given period.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param startTime the desired first execution time for the task
* (if this is in the past, the task will be executed immediately, i.e. as soon as possible)
* @param period the interval between successive executions of the task (in milliseconds)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);
/**
* Schedule the given {@link Runnable}, starting as soon as possible and
* invoking it with the given period.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param period the interval between successive executions of the task (in milliseconds)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time
* and subsequently with the given delay between the completion of one execution
* and the start of the next.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param startTime the desired first execution time for the task
* (if this is in the past, the task will be executed immediately, i.e. as soon as possible)
* @param delay the delay between the completion of one execution and the start
* of the next (in milliseconds)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
/**
* Schedule the given {@link Runnable}, starting as soon as possible and
* invoking it with the given delay between the completion of one execution
* and the start of the next.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param delay the interval between successive executions of the task (in milliseconds)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
}
/*
* Copyright 2002-2010 the original author 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;
import java.util.Date;
import java.util.concurrent.ScheduledFuture;
/**
* Task scheduler interface that abstracts the scheduling of
* {@link Runnable Runnables} based on different kinds of triggers.
*
* <p>This interface is separate from {@link SchedulingTaskExecutor} since it
* usually represents for a different kind of backend, i.e. a thread pool with
* different characteristics and capabilities. Implementations may implement
* both interfaces if they can handle both kinds of execution characteristics.
*
* <p>The 'default' implementation is
* {@link org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler},
* wrapping a native {@link java.util.concurrent.ScheduledExecutorService}
* and adding extended trigger capabilities.
*
* <p>This interface is roughly equivalent to a JSR-236
* <code>ManagedScheduledExecutorService</code> as supported in Java EE 6
* environments. However, at the time of the Spring 3.0 release, the
* JSR-236 interfaces have not been released in official form yet.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.core.task.TaskExecutor
* @see java.util.concurrent.ScheduledExecutorService
* @see org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler
*/
public interface TaskScheduler {
/**
* Schedule the given {@link Runnable}, invoking it whenever the trigger
* indicates a next execution time.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param trigger an implementation of the {@link Trigger} interface,
* e.g. a {@link org.springframework.scheduling.support.CronTrigger} object
* wrapping a cron expression
* @return a {@link ScheduledFuture} representing pending completion of the task,
* or <code>null</code> if the given Trigger object never fires (i.e. returns
* <code>null</code> from {@link Trigger#nextExecutionTime})
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
* @see org.springframework.scheduling.support.CronTrigger
*/
ScheduledFuture schedule(Runnable task, Trigger trigger);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param startTime the desired execution time for the task
* (if this is in the past, the task will be executed immediately, i.e. as soon as possible)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture schedule(Runnable task, Date startTime);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time
* and subsequently with the given period.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param startTime the desired first execution time for the task
* (if this is in the past, the task will be executed immediately, i.e. as soon as possible)
* @param period the interval between successive executions of the task (in milliseconds)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period);
/**
* Schedule the given {@link Runnable}, starting as soon as possible and
* invoking it with the given period.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param period the interval between successive executions of the task (in milliseconds)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture scheduleAtFixedRate(Runnable task, long period);
/**
* Schedule the given {@link Runnable}, invoking it at the specified execution time
* and subsequently with the given delay between the completion of one execution
* and the start of the next.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param startTime the desired first execution time for the task
* (if this is in the past, the task will be executed immediately, i.e. as soon as possible)
* @param delay the delay between the completion of one execution and the start
* of the next (in milliseconds)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay);
/**
* Schedule the given {@link Runnable}, starting as soon as possible and
* invoking it with the given delay between the completion of one execution
* and the start of the next.
* <p>Execution will end once the scheduler shuts down or the returned
* {@link ScheduledFuture} gets cancelled.
* @param task the Runnable to execute whenever the trigger fires
* @param delay the interval between successive executions of the task (in milliseconds)
* @return a {@link ScheduledFuture} representing pending completion of the task
* @throws org.springframework.core.task.TaskRejectedException if the given task was not accepted
* for internal reasons (e.g. a pool overload handling policy or a pool shutdown in progress)
*/
ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay);
}

View File

@@ -1,41 +1,41 @@
/*
* Copyright 2002-2009 the original author 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;
import java.util.Date;
/**
* Common interface for trigger objects that determine the next execution time
* of a task that they get associated with.
*
* @author Juergen Hoeller
* @since 3.0
* @see TaskScheduler#schedule(Runnable, Trigger)
* @see org.springframework.scheduling.support.CronTrigger
*/
public interface Trigger {
/**
* Determine the next execution time according to the given trigger context.
* @param triggerContext context object encapsulating last execution times
* and last completion time
* @return the next execution time as defined by the trigger,
* or <code>null</code> if the trigger won't fire anymore
*/
Date nextExecutionTime(TriggerContext triggerContext);
}
/*
* Copyright 2002-2009 the original author 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;
import java.util.Date;
/**
* Common interface for trigger objects that determine the next execution time
* of a task that they get associated with.
*
* @author Juergen Hoeller
* @since 3.0
* @see TaskScheduler#schedule(Runnable, Trigger)
* @see org.springframework.scheduling.support.CronTrigger
*/
public interface Trigger {
/**
* Determine the next execution time according to the given trigger context.
* @param triggerContext context object encapsulating last execution times
* and last completion time
* @return the next execution time as defined by the trigger,
* or <code>null</code> if the trigger won't fire anymore
*/
Date nextExecutionTime(TriggerContext triggerContext);
}

View File

@@ -1,48 +1,48 @@
/*
* Copyright 2002-2009 the original author 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;
import java.util.Date;
/**
* Context object encapsulating last execution times and last completion time
* of a given task.
*
* @author Juergen Hoeller
* @since 3.0
*/
public interface TriggerContext {
/**
* Return the last <i>scheduled</i> execution time of the task,
* or <code>null</code> if not scheduled before.
*/
Date lastScheduledExecutionTime();
/**
* Return the last <i>actual</i> execution time of the task,
* or <code>null</code> if not scheduled before.
*/
Date lastActualExecutionTime();
/**
* Return the last completion time of the task,
* or <code>null</code> if not scheduled before.
*/
Date lastCompletionTime();
}
/*
* Copyright 2002-2009 the original author 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;
import java.util.Date;
/**
* Context object encapsulating last execution times and last completion time
* of a given task.
*
* @author Juergen Hoeller
* @since 3.0
*/
public interface TriggerContext {
/**
* Return the last <i>scheduled</i> execution time of the task,
* or <code>null</code> if not scheduled before.
*/
Date lastScheduledExecutionTime();
/**
* Return the last <i>actual</i> execution time of the task,
* or <code>null</code> if not scheduled before.
*/
Date lastActualExecutionTime();
/**
* Return the last completion time of the task,
* or <code>null</code> if not scheduled before.
*/
Date lastCompletionTime();
}

View File

@@ -1,49 +1,49 @@
/*
* Copyright 2002-2009 the original author 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.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that marks a method as a candidate for <i>asynchronous</i> execution.
* Can also be used at the type level, in which case all of the type's methods are
* considered as asynchronous.
*
* <p>In terms of target method signatures, any parameter types are supported.
* However, the return type is constrained to either <code>void</code> or
* <code>java.util.concurrent.Future</code>. In the latter case, the Future handle
* returned from the proxy will be an actual asynchronous Future that can be used
* to track the result of the asynchronous method execution. However, since the
* target method needs to implement the same signature, it will have to return
* a temporary Future handle that just passes the return value through: e.g.
* Spring's {@link AsyncResult} or EJB 3.1's <code>javax.ejb.AsyncResult</code>.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.aop.interceptor.AsyncExecutionInterceptor
* @see AsyncAnnotationAdvisor
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
}
/*
* Copyright 2002-2009 the original author 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.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that marks a method as a candidate for <i>asynchronous</i> execution.
* Can also be used at the type level, in which case all of the type's methods are
* considered as asynchronous.
*
* <p>In terms of target method signatures, any parameter types are supported.
* However, the return type is constrained to either <code>void</code> or
* <code>java.util.concurrent.Future</code>. In the latter case, the Future handle
* returned from the proxy will be an actual asynchronous Future that can be used
* to track the result of the asynchronous method execution. However, since the
* target method needs to implement the same signature, it will have to return
* a temporary Future handle that just passes the return value through: e.g.
* Spring's {@link AsyncResult} or EJB 3.1's <code>javax.ejb.AsyncResult</code>.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.aop.interceptor.AsyncExecutionInterceptor
* @see AsyncAnnotationAdvisor
*/
@Target({ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Async {
}

View File

@@ -1,63 +1,63 @@
/*
* Copyright 2002-2009 the original author 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.annotation;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* A pass-through <code>Future</code> handle that can be used for method signatures
* which are declared with a Future return type for asynchronous execution.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.scheduling.annotation.Async
*/
public class AsyncResult<V> implements Future<V> {
private final V value;
/**
* Create a new AsyncResult holder.
* @param value the value to pass through
*/
public AsyncResult(V value) {
this.value = value;
}
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
public boolean isCancelled() {
return false;
}
public boolean isDone() {
return true;
}
public V get() {
return this.value;
}
public V get(long timeout, TimeUnit unit) {
return this.value;
}
}
/*
* Copyright 2002-2009 the original author 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.annotation;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
/**
* A pass-through <code>Future</code> handle that can be used for method signatures
* which are declared with a Future return type for asynchronous execution.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.scheduling.annotation.Async
*/
public class AsyncResult<V> implements Future<V> {
private final V value;
/**
* Create a new AsyncResult holder.
* @param value the value to pass through
*/
public AsyncResult(V value) {
this.value = value;
}
public boolean cancel(boolean mayInterruptIfRunning) {
return false;
}
public boolean isCancelled() {
return false;
}
public boolean isDone() {
return true;
}
public V get() {
return this.value;
}
public V get(long timeout, TimeUnit unit) {
return this.value;
}
}

View File

@@ -1,71 +1,71 @@
/*
* Copyright 2002-2011 the original author 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.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that marks a method to be scheduled. Exactly one of the
* <code>cron</code>, <code>fixedDelay</code>, or <code>fixedRate</code>
* attributes must be provided.
*
* <p>The annotated method must expect no arguments and have a
* <code>void</code> return type.
*
* <p>Processing of {@code @Scheduled} annotations is performed by
* registering a {@link ScheduledAnnotationBeanPostProcessor}. This can be
* done manually or, more conveniently, through the {@code <task:annotation-driven/>}
* element or @{@link EnableScheduling} annotation.
*
* @author Mark Fisher
* @author Dave Syer
* @since 3.0
* @see EnableScheduling
* @see ScheduledAnnotationBeanPostProcessor
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scheduled {
/**
* A cron-like expression, extending the usual UN*X definition to include
* triggers on the second as well as minute, hour, day of month, month
* and day of week. e.g. <code>"0 * * * * MON-FRI"</code> means once
* per minute on weekdays (at the top of the minute - the 0th second).
* @return an expression that can be parsed to a cron schedule
*/
String cron() default "";
/**
* Execute the annotated method with a fixed period between the end
* of the last invocation and the start of the next.
* @return the delay in milliseconds
*/
long fixedDelay() default -1;
/**
* Execute the annotated method with a fixed period between invocations.
* @return the period in milliseconds
*/
long fixedRate() default -1;
}
/*
* Copyright 2002-2011 the original author 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.annotation;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation that marks a method to be scheduled. Exactly one of the
* <code>cron</code>, <code>fixedDelay</code>, or <code>fixedRate</code>
* attributes must be provided.
*
* <p>The annotated method must expect no arguments and have a
* <code>void</code> return type.
*
* <p>Processing of {@code @Scheduled} annotations is performed by
* registering a {@link ScheduledAnnotationBeanPostProcessor}. This can be
* done manually or, more conveniently, through the {@code <task:annotation-driven/>}
* element or @{@link EnableScheduling} annotation.
*
* @author Mark Fisher
* @author Dave Syer
* @since 3.0
* @see EnableScheduling
* @see ScheduledAnnotationBeanPostProcessor
*/
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Scheduled {
/**
* A cron-like expression, extending the usual UN*X definition to include
* triggers on the second as well as minute, hour, day of month, month
* and day of week. e.g. <code>"0 * * * * MON-FRI"</code> means once
* per minute on weekdays (at the top of the minute - the 0th second).
* @return an expression that can be parsed to a cron schedule
*/
String cron() default "";
/**
* Execute the annotated method with a fixed period between the end
* of the last invocation and the start of the next.
* @return the delay in milliseconds
*/
long fixedDelay() default -1;
/**
* Execute the annotated method with a fixed period between invocations.
* @return the period in milliseconds
*/
long fixedRate() default -1;
}

View File

@@ -1,187 +1,187 @@
/*
* Copyright 2002-2011 the original author 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.concurrent;
import java.util.Date;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert;
import org.springframework.util.ErrorHandler;
/**
* Adapter that takes a JDK 1.5 <code>java.util.concurrent.ScheduledExecutorService</code>
* and exposes a Spring {@link org.springframework.scheduling.TaskScheduler} for it.
* Extends {@link ConcurrentTaskExecutor} in order to implement the
* {@link org.springframework.scheduling.SchedulingTaskExecutor} interface as well.
*
* <p>Note that there is a pre-built {@link ThreadPoolTaskScheduler} that allows for
* defining a JDK 1.5 {@link java.util.concurrent.ScheduledThreadPoolExecutor} in bean style,
* exposing it as a Spring {@link org.springframework.scheduling.TaskScheduler} directly.
* This is a convenient alternative to a raw ScheduledThreadPoolExecutor definition with
* a separate definition of the present adapter class.
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 3.0
* @see java.util.concurrent.ScheduledExecutorService
* @see java.util.concurrent.ScheduledThreadPoolExecutor
* @see java.util.concurrent.Executors
* @see ThreadPoolTaskScheduler
*/
public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements TaskScheduler {
private volatile ScheduledExecutorService scheduledExecutor;
private volatile ErrorHandler errorHandler;
/**
* Create a new ConcurrentTaskScheduler,
* using a single thread executor as default.
* @see java.util.concurrent.Executors#newSingleThreadScheduledExecutor()
*/
public ConcurrentTaskScheduler() {
super();
setScheduledExecutor(null);
}
/**
* Create a new ConcurrentTaskScheduler,
* using the given JDK 1.5 executor as shared delegate.
* @param scheduledExecutor the JDK 1.5 scheduled executor to delegate to
* for {@link org.springframework.scheduling.SchedulingTaskExecutor} as well
* as {@link TaskScheduler} invocations
*/
public ConcurrentTaskScheduler(ScheduledExecutorService scheduledExecutor) {
super(scheduledExecutor);
setScheduledExecutor(scheduledExecutor);
}
/**
* Create a new ConcurrentTaskScheduler,
* using the given JDK 1.5 executors as delegates.
* @param concurrentExecutor the JDK 1.5 concurrent executor to delegate to
* for {@link org.springframework.scheduling.SchedulingTaskExecutor} invocations
* @param scheduledExecutor the JDK 1.5 scheduled executor to delegate to
* for {@link TaskScheduler} invocations
*/
public ConcurrentTaskScheduler(Executor concurrentExecutor, ScheduledExecutorService scheduledExecutor) {
super(concurrentExecutor);
setScheduledExecutor(scheduledExecutor);
}
/**
* Specify the JDK 1.5 scheduled executor to delegate to.
* <p>Note: This will only apply to {@link TaskScheduler} invocations.
* If you want the given executor to apply to
* {@link org.springframework.scheduling.SchedulingTaskExecutor} invocations
* as well, pass the same executor reference to {@link #setConcurrentExecutor}.
* @see #setConcurrentExecutor
*/
public final void setScheduledExecutor(ScheduledExecutorService scheduledExecutor) {
this.scheduledExecutor =
(scheduledExecutor != null ? scheduledExecutor : Executors.newSingleThreadScheduledExecutor());
}
/**
* Provide an {@link ErrorHandler} strategy.
*/
public void setErrorHandler(ErrorHandler errorHandler) {
Assert.notNull(errorHandler, "'errorHandler' must not be null");
this.errorHandler = errorHandler;
}
public ScheduledFuture schedule(Runnable task, Trigger trigger) {
try {
ErrorHandler errorHandler =
(this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
return new ReschedulingRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule();
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture schedule(Runnable task, Date startTime) {
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return this.scheduledExecutor.schedule(
errorHandlingTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period) {
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return this.scheduledExecutor.scheduleAtFixedRate(
errorHandlingTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleAtFixedRate(Runnable task, long period) {
try {
return this.scheduledExecutor.scheduleAtFixedRate(
errorHandlingTask(task, true), 0, period, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return this.scheduledExecutor.scheduleWithFixedDelay(
errorHandlingTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay) {
try {
return this.scheduledExecutor.scheduleWithFixedDelay(
errorHandlingTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
private Runnable errorHandlingTask(Runnable task, boolean isRepeatingTask) {
return TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, isRepeatingTask);
}
}
/*
* Copyright 2002-2011 the original author 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.concurrent;
import java.util.Date;
import java.util.concurrent.Executor;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert;
import org.springframework.util.ErrorHandler;
/**
* Adapter that takes a JDK 1.5 <code>java.util.concurrent.ScheduledExecutorService</code>
* and exposes a Spring {@link org.springframework.scheduling.TaskScheduler} for it.
* Extends {@link ConcurrentTaskExecutor} in order to implement the
* {@link org.springframework.scheduling.SchedulingTaskExecutor} interface as well.
*
* <p>Note that there is a pre-built {@link ThreadPoolTaskScheduler} that allows for
* defining a JDK 1.5 {@link java.util.concurrent.ScheduledThreadPoolExecutor} in bean style,
* exposing it as a Spring {@link org.springframework.scheduling.TaskScheduler} directly.
* This is a convenient alternative to a raw ScheduledThreadPoolExecutor definition with
* a separate definition of the present adapter class.
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 3.0
* @see java.util.concurrent.ScheduledExecutorService
* @see java.util.concurrent.ScheduledThreadPoolExecutor
* @see java.util.concurrent.Executors
* @see ThreadPoolTaskScheduler
*/
public class ConcurrentTaskScheduler extends ConcurrentTaskExecutor implements TaskScheduler {
private volatile ScheduledExecutorService scheduledExecutor;
private volatile ErrorHandler errorHandler;
/**
* Create a new ConcurrentTaskScheduler,
* using a single thread executor as default.
* @see java.util.concurrent.Executors#newSingleThreadScheduledExecutor()
*/
public ConcurrentTaskScheduler() {
super();
setScheduledExecutor(null);
}
/**
* Create a new ConcurrentTaskScheduler,
* using the given JDK 1.5 executor as shared delegate.
* @param scheduledExecutor the JDK 1.5 scheduled executor to delegate to
* for {@link org.springframework.scheduling.SchedulingTaskExecutor} as well
* as {@link TaskScheduler} invocations
*/
public ConcurrentTaskScheduler(ScheduledExecutorService scheduledExecutor) {
super(scheduledExecutor);
setScheduledExecutor(scheduledExecutor);
}
/**
* Create a new ConcurrentTaskScheduler,
* using the given JDK 1.5 executors as delegates.
* @param concurrentExecutor the JDK 1.5 concurrent executor to delegate to
* for {@link org.springframework.scheduling.SchedulingTaskExecutor} invocations
* @param scheduledExecutor the JDK 1.5 scheduled executor to delegate to
* for {@link TaskScheduler} invocations
*/
public ConcurrentTaskScheduler(Executor concurrentExecutor, ScheduledExecutorService scheduledExecutor) {
super(concurrentExecutor);
setScheduledExecutor(scheduledExecutor);
}
/**
* Specify the JDK 1.5 scheduled executor to delegate to.
* <p>Note: This will only apply to {@link TaskScheduler} invocations.
* If you want the given executor to apply to
* {@link org.springframework.scheduling.SchedulingTaskExecutor} invocations
* as well, pass the same executor reference to {@link #setConcurrentExecutor}.
* @see #setConcurrentExecutor
*/
public final void setScheduledExecutor(ScheduledExecutorService scheduledExecutor) {
this.scheduledExecutor =
(scheduledExecutor != null ? scheduledExecutor : Executors.newSingleThreadScheduledExecutor());
}
/**
* Provide an {@link ErrorHandler} strategy.
*/
public void setErrorHandler(ErrorHandler errorHandler) {
Assert.notNull(errorHandler, "'errorHandler' must not be null");
this.errorHandler = errorHandler;
}
public ScheduledFuture schedule(Runnable task, Trigger trigger) {
try {
ErrorHandler errorHandler =
(this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
return new ReschedulingRunnable(task, trigger, this.scheduledExecutor, errorHandler).schedule();
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture schedule(Runnable task, Date startTime) {
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return this.scheduledExecutor.schedule(
errorHandlingTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period) {
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return this.scheduledExecutor.scheduleAtFixedRate(
errorHandlingTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleAtFixedRate(Runnable task, long period) {
try {
return this.scheduledExecutor.scheduleAtFixedRate(
errorHandlingTask(task, true), 0, period, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return this.scheduledExecutor.scheduleWithFixedDelay(
errorHandlingTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay) {
try {
return this.scheduledExecutor.scheduleWithFixedDelay(
errorHandlingTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + this.scheduledExecutor + "] did not accept task: " + task, ex);
}
}
private Runnable errorHandlingTask(Runnable task, boolean isRepeatingTask) {
return TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, isRepeatingTask);
}
}

View File

@@ -1,160 +1,160 @@
/*
* Copyright 2002-2009 the original author 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.concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* Base class for classes that are setting up a
* <code>java.util.concurrent.ExecutorService</code>
* (typically a {@link java.util.concurrent.ThreadPoolExecutor}).
* Defines common configuration settings and common lifecycle handling.
*
* @author Juergen Hoeller
* @since 3.0
* @see java.util.concurrent.ExecutorService
* @see java.util.concurrent.Executors
* @see java.util.concurrent.ThreadPoolExecutor
*/
public abstract class ExecutorConfigurationSupport extends CustomizableThreadFactory
implements BeanNameAware, InitializingBean, DisposableBean {
protected final Log logger = LogFactory.getLog(getClass());
private ThreadFactory threadFactory = this;
private boolean threadNamePrefixSet = false;
private RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();
private boolean waitForTasksToCompleteOnShutdown = false;
private String beanName;
private ExecutorService executor;
/**
* Set the ThreadFactory to use for the ThreadPoolExecutor's thread pool.
* Default is the ThreadPoolExecutor's default thread factory.
* @see java.util.concurrent.Executors#defaultThreadFactory()
*/
public void setThreadFactory(ThreadFactory threadFactory) {
this.threadFactory = (threadFactory != null ? threadFactory : this);
}
@Override
public void setThreadNamePrefix(String threadNamePrefix) {
super.setThreadNamePrefix(threadNamePrefix);
this.threadNamePrefixSet = true;
}
/**
* Set the RejectedExecutionHandler to use for the ThreadPoolExecutor.
* Default is the ThreadPoolExecutor's default abort policy.
* @see java.util.concurrent.ThreadPoolExecutor.AbortPolicy
*/
public void setRejectedExecutionHandler(RejectedExecutionHandler rejectedExecutionHandler) {
this.rejectedExecutionHandler =
(rejectedExecutionHandler != null ? rejectedExecutionHandler : new ThreadPoolExecutor.AbortPolicy());
}
/**
* Set whether to wait for scheduled tasks to complete on shutdown.
* <p>Default is "false". Switch this to "true" if you prefer
* fully completed tasks at the expense of a longer shutdown phase.
* @see java.util.concurrent.ExecutorService#shutdown()
* @see java.util.concurrent.ExecutorService#shutdownNow()
*/
public void setWaitForTasksToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
this.waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
}
public void setBeanName(String name) {
this.beanName = name;
}
/**
* Calls <code>initialize()</code> after the container applied all property values.
* @see #initialize()
*/
public void afterPropertiesSet() {
initialize();
}
/**
* Set up the ExecutorService.
*/
public void initialize() {
if (logger.isInfoEnabled()) {
logger.info("Initializing ExecutorService " + (this.beanName != null ? " '" + this.beanName + "'" : ""));
}
if (!this.threadNamePrefixSet && this.beanName != null) {
setThreadNamePrefix(this.beanName + "-");
}
this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
}
/**
* Create the target {@link java.util.concurrent.ExecutorService} instance.
* Called by <code>afterPropertiesSet</code>.
* @param threadFactory the ThreadFactory to use
* @param rejectedExecutionHandler the RejectedExecutionHandler to use
* @return a new ExecutorService instance
* @see #afterPropertiesSet()
*/
protected abstract ExecutorService initializeExecutor(
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler);
/**
* Calls <code>shutdown</code> when the BeanFactory destroys
* the task executor instance.
* @see #shutdown()
*/
public void destroy() {
shutdown();
}
/**
* Perform a shutdown on the ThreadPoolExecutor.
* @see java.util.concurrent.ExecutorService#shutdown()
*/
public void shutdown() {
if (logger.isInfoEnabled()) {
logger.info("Shutting down ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
}
if (this.waitForTasksToCompleteOnShutdown) {
this.executor.shutdown();
}
else {
this.executor.shutdownNow();
}
}
}
/*
* Copyright 2002-2009 the original author 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.concurrent;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
/**
* Base class for classes that are setting up a
* <code>java.util.concurrent.ExecutorService</code>
* (typically a {@link java.util.concurrent.ThreadPoolExecutor}).
* Defines common configuration settings and common lifecycle handling.
*
* @author Juergen Hoeller
* @since 3.0
* @see java.util.concurrent.ExecutorService
* @see java.util.concurrent.Executors
* @see java.util.concurrent.ThreadPoolExecutor
*/
public abstract class ExecutorConfigurationSupport extends CustomizableThreadFactory
implements BeanNameAware, InitializingBean, DisposableBean {
protected final Log logger = LogFactory.getLog(getClass());
private ThreadFactory threadFactory = this;
private boolean threadNamePrefixSet = false;
private RejectedExecutionHandler rejectedExecutionHandler = new ThreadPoolExecutor.AbortPolicy();
private boolean waitForTasksToCompleteOnShutdown = false;
private String beanName;
private ExecutorService executor;
/**
* Set the ThreadFactory to use for the ThreadPoolExecutor's thread pool.
* Default is the ThreadPoolExecutor's default thread factory.
* @see java.util.concurrent.Executors#defaultThreadFactory()
*/
public void setThreadFactory(ThreadFactory threadFactory) {
this.threadFactory = (threadFactory != null ? threadFactory : this);
}
@Override
public void setThreadNamePrefix(String threadNamePrefix) {
super.setThreadNamePrefix(threadNamePrefix);
this.threadNamePrefixSet = true;
}
/**
* Set the RejectedExecutionHandler to use for the ThreadPoolExecutor.
* Default is the ThreadPoolExecutor's default abort policy.
* @see java.util.concurrent.ThreadPoolExecutor.AbortPolicy
*/
public void setRejectedExecutionHandler(RejectedExecutionHandler rejectedExecutionHandler) {
this.rejectedExecutionHandler =
(rejectedExecutionHandler != null ? rejectedExecutionHandler : new ThreadPoolExecutor.AbortPolicy());
}
/**
* Set whether to wait for scheduled tasks to complete on shutdown.
* <p>Default is "false". Switch this to "true" if you prefer
* fully completed tasks at the expense of a longer shutdown phase.
* @see java.util.concurrent.ExecutorService#shutdown()
* @see java.util.concurrent.ExecutorService#shutdownNow()
*/
public void setWaitForTasksToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
this.waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
}
public void setBeanName(String name) {
this.beanName = name;
}
/**
* Calls <code>initialize()</code> after the container applied all property values.
* @see #initialize()
*/
public void afterPropertiesSet() {
initialize();
}
/**
* Set up the ExecutorService.
*/
public void initialize() {
if (logger.isInfoEnabled()) {
logger.info("Initializing ExecutorService " + (this.beanName != null ? " '" + this.beanName + "'" : ""));
}
if (!this.threadNamePrefixSet && this.beanName != null) {
setThreadNamePrefix(this.beanName + "-");
}
this.executor = initializeExecutor(this.threadFactory, this.rejectedExecutionHandler);
}
/**
* Create the target {@link java.util.concurrent.ExecutorService} instance.
* Called by <code>afterPropertiesSet</code>.
* @param threadFactory the ThreadFactory to use
* @param rejectedExecutionHandler the RejectedExecutionHandler to use
* @return a new ExecutorService instance
* @see #afterPropertiesSet()
*/
protected abstract ExecutorService initializeExecutor(
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler);
/**
* Calls <code>shutdown</code> when the BeanFactory destroys
* the task executor instance.
* @see #shutdown()
*/
public void destroy() {
shutdown();
}
/**
* Perform a shutdown on the ThreadPoolExecutor.
* @see java.util.concurrent.ExecutorService#shutdown()
*/
public void shutdown() {
if (logger.isInfoEnabled()) {
logger.info("Shutting down ExecutorService" + (this.beanName != null ? " '" + this.beanName + "'" : ""));
}
if (this.waitForTasksToCompleteOnShutdown) {
this.executor.shutdown();
}
else {
this.executor.shutdownNow();
}
}
}

View File

@@ -1,124 +1,124 @@
/*
* Copyright 2002-2009 the original author 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.concurrent;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.util.ErrorHandler;
/**
* Internal adapter that reschedules an underlying {@link Runnable} according
* to the next execution time suggested by a given {@link Trigger}.
*
* <p>Necessary because a native {@link ScheduledExecutorService} supports
* delay-driven execution only. The flexibility of the {@link Trigger} interface
* will be translated onto a delay for the next execution time (repeatedly).
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 3.0
*/
class ReschedulingRunnable extends DelegatingErrorHandlingRunnable implements ScheduledFuture<Object> {
private final Trigger trigger;
private final SimpleTriggerContext triggerContext = new SimpleTriggerContext();
private final ScheduledExecutorService executor;
private volatile ScheduledFuture currentFuture;
private volatile Date scheduledExecutionTime;
private final Object triggerContextMonitor = new Object();
public ReschedulingRunnable(Runnable delegate, Trigger trigger, ScheduledExecutorService executor, ErrorHandler errorHandler) {
super(delegate, errorHandler);
this.trigger = trigger;
this.executor = executor;
}
public ScheduledFuture schedule() {
synchronized (this.triggerContextMonitor) {
this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (this.scheduledExecutionTime == null) {
return null;
}
long initialDelay = this.scheduledExecutionTime.getTime() - System.currentTimeMillis();
this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
return this;
}
}
@Override
public void run() {
Date actualExecutionTime = new Date();
super.run();
Date completionTime = new Date();
synchronized (this.triggerContextMonitor) {
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
}
if (!this.currentFuture.isCancelled()) {
schedule();
}
}
public boolean cancel(boolean mayInterruptIfRunning) {
return this.currentFuture.cancel(mayInterruptIfRunning);
}
public boolean isCancelled() {
return this.currentFuture.isCancelled();
}
public boolean isDone() {
return this.currentFuture.isDone();
}
public Object get() throws InterruptedException, ExecutionException {
return this.currentFuture.get();
}
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return this.currentFuture.get(timeout, unit);
}
public long getDelay(TimeUnit unit) {
return this.currentFuture.getDelay(unit);
}
public int compareTo(Delayed other) {
if (this == other) {
return 0;
}
long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS);
return (diff == 0 ? 0 : ((diff < 0)? -1 : 1));
}
}
/*
* Copyright 2002-2009 the original author 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.concurrent;
import java.util.Date;
import java.util.concurrent.Delayed;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.DelegatingErrorHandlingRunnable;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.util.ErrorHandler;
/**
* Internal adapter that reschedules an underlying {@link Runnable} according
* to the next execution time suggested by a given {@link Trigger}.
*
* <p>Necessary because a native {@link ScheduledExecutorService} supports
* delay-driven execution only. The flexibility of the {@link Trigger} interface
* will be translated onto a delay for the next execution time (repeatedly).
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 3.0
*/
class ReschedulingRunnable extends DelegatingErrorHandlingRunnable implements ScheduledFuture<Object> {
private final Trigger trigger;
private final SimpleTriggerContext triggerContext = new SimpleTriggerContext();
private final ScheduledExecutorService executor;
private volatile ScheduledFuture currentFuture;
private volatile Date scheduledExecutionTime;
private final Object triggerContextMonitor = new Object();
public ReschedulingRunnable(Runnable delegate, Trigger trigger, ScheduledExecutorService executor, ErrorHandler errorHandler) {
super(delegate, errorHandler);
this.trigger = trigger;
this.executor = executor;
}
public ScheduledFuture schedule() {
synchronized (this.triggerContextMonitor) {
this.scheduledExecutionTime = this.trigger.nextExecutionTime(this.triggerContext);
if (this.scheduledExecutionTime == null) {
return null;
}
long initialDelay = this.scheduledExecutionTime.getTime() - System.currentTimeMillis();
this.currentFuture = this.executor.schedule(this, initialDelay, TimeUnit.MILLISECONDS);
return this;
}
}
@Override
public void run() {
Date actualExecutionTime = new Date();
super.run();
Date completionTime = new Date();
synchronized (this.triggerContextMonitor) {
this.triggerContext.update(this.scheduledExecutionTime, actualExecutionTime, completionTime);
}
if (!this.currentFuture.isCancelled()) {
schedule();
}
}
public boolean cancel(boolean mayInterruptIfRunning) {
return this.currentFuture.cancel(mayInterruptIfRunning);
}
public boolean isCancelled() {
return this.currentFuture.isCancelled();
}
public boolean isDone() {
return this.currentFuture.isDone();
}
public Object get() throws InterruptedException, ExecutionException {
return this.currentFuture.get();
}
public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
return this.currentFuture.get(timeout, unit);
}
public long getDelay(TimeUnit unit) {
return this.currentFuture.getDelay(unit);
}
public int compareTo(Delayed other) {
if (this == other) {
return 0;
}
long diff = getDelay(TimeUnit.MILLISECONDS) - other.getDelay(TimeUnit.MILLISECONDS);
return (diff == 0 ? 0 : ((diff < 0)? -1 : 1));
}
}

View File

@@ -1,251 +1,251 @@
/*
* Copyright 2002-2011 the original author 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.concurrent;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert;
import org.springframework.util.ErrorHandler;
/**
* Implementation of Spring's {@link TaskScheduler} interface, wrapping
* a native {@link java.util.concurrent.ScheduledThreadPoolExecutor}.
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 3.0
* @see #setPoolSize
* @see #setThreadFactory
* @see #setErrorHandler
*/
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
implements TaskScheduler, SchedulingTaskExecutor {
private volatile int poolSize = 1;
private volatile ScheduledExecutorService scheduledExecutor;
private volatile ErrorHandler errorHandler;
/**
* Set the ScheduledExecutorService's pool size.
* Default is 1.
*/
public void setPoolSize(int poolSize) {
Assert.isTrue(poolSize > 0, "'poolSize' must be 1 or higher");
this.poolSize = poolSize;
}
/**
* Provide an {@link ErrorHandler} strategy.
*/
public void setErrorHandler(ErrorHandler errorHandler) {
Assert.notNull(errorHandler, "'errorHandler' must not be null");
this.errorHandler = errorHandler;
}
protected ExecutorService initializeExecutor(
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
return this.scheduledExecutor;
}
/**
* Create a new {@link ScheduledExecutorService} instance.
* <p>The default implementation creates a {@link ScheduledThreadPoolExecutor}.
* Can be overridden in subclasses to provide custom {@link ScheduledExecutorService} instances.
* @param poolSize the specified pool size
* @param threadFactory the ThreadFactory to use
* @param rejectedExecutionHandler the RejectedExecutionHandler to use
* @return a new ScheduledExecutorService instance
* @see #afterPropertiesSet()
* @see java.util.concurrent.ScheduledThreadPoolExecutor
*/
protected ScheduledExecutorService createExecutor(
int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
return new ScheduledThreadPoolExecutor(poolSize, threadFactory, rejectedExecutionHandler);
}
/**
* Return the underlying ScheduledExecutorService for native access.
* @return the underlying ScheduledExecutorService (never <code>null</code>)
* @throws IllegalStateException if the ThreadPoolTaskScheduler hasn't been initialized yet
*/
public ScheduledExecutorService getScheduledExecutor() throws IllegalStateException {
Assert.state(this.scheduledExecutor != null, "ThreadPoolTaskScheduler not initialized");
return this.scheduledExecutor;
}
// SchedulingTaskExecutor implementation
public void execute(Runnable task) {
Executor executor = getScheduledExecutor();
try {
executor.execute(errorHandlingTask(task, false));
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public void execute(Runnable task, long startTimeout) {
execute(task);
}
public Future<?> submit(Runnable task) {
ExecutorService executor = getScheduledExecutor();
try {
return executor.submit(errorHandlingTask(task, false));
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public <T> Future<T> submit(Callable<T> task) {
ExecutorService executor = getScheduledExecutor();
try {
if (this.errorHandler != null) {
task = new DelegatingErrorHandlingCallable<T>(task, this.errorHandler);
}
return executor.submit(task);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public boolean prefersShortLivedTasks() {
return true;
}
// TaskScheduler implementation
public ScheduledFuture schedule(Runnable task, Trigger trigger) {
ScheduledExecutorService executor = getScheduledExecutor();
try {
ErrorHandler errorHandler =
(this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture schedule(Runnable task, Date startTime) {
ScheduledExecutorService executor = getScheduledExecutor();
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return executor.schedule(errorHandlingTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period) {
ScheduledExecutorService executor = getScheduledExecutor();
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return executor.scheduleAtFixedRate(errorHandlingTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleAtFixedRate(Runnable task, long period) {
ScheduledExecutorService executor = getScheduledExecutor();
try {
return executor.scheduleAtFixedRate(errorHandlingTask(task, true), 0, period, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
ScheduledExecutorService executor = getScheduledExecutor();
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay) {
ScheduledExecutorService executor = getScheduledExecutor();
try {
return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
private Runnable errorHandlingTask(Runnable task, boolean isRepeatingTask) {
return TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, isRepeatingTask);
}
private static class DelegatingErrorHandlingCallable<V> implements Callable<V> {
private final Callable<V> delegate;
private final ErrorHandler errorHandler;
DelegatingErrorHandlingCallable(Callable<V> delegate, ErrorHandler errorHandler) {
this.delegate = delegate;
this.errorHandler = errorHandler;
}
public V call() throws Exception {
try {
return delegate.call();
}
catch (Throwable t) {
this.errorHandler.handleError(t);
return null;
}
}
}
}
/*
* Copyright 2002-2011 the original author 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.concurrent;
import java.util.Date;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.RejectedExecutionException;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import org.springframework.core.task.TaskRejectedException;
import org.springframework.scheduling.SchedulingTaskExecutor;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.support.TaskUtils;
import org.springframework.util.Assert;
import org.springframework.util.ErrorHandler;
/**
* Implementation of Spring's {@link TaskScheduler} interface, wrapping
* a native {@link java.util.concurrent.ScheduledThreadPoolExecutor}.
*
* @author Juergen Hoeller
* @author Mark Fisher
* @since 3.0
* @see #setPoolSize
* @see #setThreadFactory
* @see #setErrorHandler
*/
public class ThreadPoolTaskScheduler extends ExecutorConfigurationSupport
implements TaskScheduler, SchedulingTaskExecutor {
private volatile int poolSize = 1;
private volatile ScheduledExecutorService scheduledExecutor;
private volatile ErrorHandler errorHandler;
/**
* Set the ScheduledExecutorService's pool size.
* Default is 1.
*/
public void setPoolSize(int poolSize) {
Assert.isTrue(poolSize > 0, "'poolSize' must be 1 or higher");
this.poolSize = poolSize;
}
/**
* Provide an {@link ErrorHandler} strategy.
*/
public void setErrorHandler(ErrorHandler errorHandler) {
Assert.notNull(errorHandler, "'errorHandler' must not be null");
this.errorHandler = errorHandler;
}
protected ExecutorService initializeExecutor(
ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
this.scheduledExecutor = createExecutor(this.poolSize, threadFactory, rejectedExecutionHandler);
return this.scheduledExecutor;
}
/**
* Create a new {@link ScheduledExecutorService} instance.
* <p>The default implementation creates a {@link ScheduledThreadPoolExecutor}.
* Can be overridden in subclasses to provide custom {@link ScheduledExecutorService} instances.
* @param poolSize the specified pool size
* @param threadFactory the ThreadFactory to use
* @param rejectedExecutionHandler the RejectedExecutionHandler to use
* @return a new ScheduledExecutorService instance
* @see #afterPropertiesSet()
* @see java.util.concurrent.ScheduledThreadPoolExecutor
*/
protected ScheduledExecutorService createExecutor(
int poolSize, ThreadFactory threadFactory, RejectedExecutionHandler rejectedExecutionHandler) {
return new ScheduledThreadPoolExecutor(poolSize, threadFactory, rejectedExecutionHandler);
}
/**
* Return the underlying ScheduledExecutorService for native access.
* @return the underlying ScheduledExecutorService (never <code>null</code>)
* @throws IllegalStateException if the ThreadPoolTaskScheduler hasn't been initialized yet
*/
public ScheduledExecutorService getScheduledExecutor() throws IllegalStateException {
Assert.state(this.scheduledExecutor != null, "ThreadPoolTaskScheduler not initialized");
return this.scheduledExecutor;
}
// SchedulingTaskExecutor implementation
public void execute(Runnable task) {
Executor executor = getScheduledExecutor();
try {
executor.execute(errorHandlingTask(task, false));
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public void execute(Runnable task, long startTimeout) {
execute(task);
}
public Future<?> submit(Runnable task) {
ExecutorService executor = getScheduledExecutor();
try {
return executor.submit(errorHandlingTask(task, false));
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public <T> Future<T> submit(Callable<T> task) {
ExecutorService executor = getScheduledExecutor();
try {
if (this.errorHandler != null) {
task = new DelegatingErrorHandlingCallable<T>(task, this.errorHandler);
}
return executor.submit(task);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public boolean prefersShortLivedTasks() {
return true;
}
// TaskScheduler implementation
public ScheduledFuture schedule(Runnable task, Trigger trigger) {
ScheduledExecutorService executor = getScheduledExecutor();
try {
ErrorHandler errorHandler =
(this.errorHandler != null ? this.errorHandler : TaskUtils.getDefaultErrorHandler(true));
return new ReschedulingRunnable(task, trigger, executor, errorHandler).schedule();
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture schedule(Runnable task, Date startTime) {
ScheduledExecutorService executor = getScheduledExecutor();
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return executor.schedule(errorHandlingTask(task, false), initialDelay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleAtFixedRate(Runnable task, Date startTime, long period) {
ScheduledExecutorService executor = getScheduledExecutor();
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return executor.scheduleAtFixedRate(errorHandlingTask(task, true), initialDelay, period, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleAtFixedRate(Runnable task, long period) {
ScheduledExecutorService executor = getScheduledExecutor();
try {
return executor.scheduleAtFixedRate(errorHandlingTask(task, true), 0, period, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleWithFixedDelay(Runnable task, Date startTime, long delay) {
ScheduledExecutorService executor = getScheduledExecutor();
long initialDelay = startTime.getTime() - System.currentTimeMillis();
try {
return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), initialDelay, delay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
public ScheduledFuture scheduleWithFixedDelay(Runnable task, long delay) {
ScheduledExecutorService executor = getScheduledExecutor();
try {
return executor.scheduleWithFixedDelay(errorHandlingTask(task, true), 0, delay, TimeUnit.MILLISECONDS);
}
catch (RejectedExecutionException ex) {
throw new TaskRejectedException("Executor [" + executor + "] did not accept task: " + task, ex);
}
}
private Runnable errorHandlingTask(Runnable task, boolean isRepeatingTask) {
return TaskUtils.decorateTaskWithErrorHandler(task, this.errorHandler, isRepeatingTask);
}
private static class DelegatingErrorHandlingCallable<V> implements Callable<V> {
private final Callable<V> delegate;
private final ErrorHandler errorHandler;
DelegatingErrorHandlingCallable(Callable<V> delegate, ErrorHandler errorHandler) {
this.delegate = delegate;
this.errorHandler = errorHandler;
}
public V call() throws Exception {
try {
return delegate.call();
}
catch (Throwable t) {
this.errorHandler.handleError(t);
return null;
}
}
}
}

View File

@@ -1,213 +1,213 @@
/*
* Copyright 2002-2011 the original author 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 java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.Assert;
/**
* Helper bean for registering tasks with a {@link TaskScheduler},
* typically using cron expressions.
*
* <p>As of Spring 3.1, {@code ScheduledTaskRegistrar} has a more prominent user-facing
* role when used in conjunction with the @{@link
* org.springframework.scheduling.annotation.EnableAsync EnableAsync} annotation and its
* {@link org.springframework.scheduling.annotation.SchedulingConfigurer
* SchedulingConfigurer} callback interface.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.scheduling.annotation.EnableAsync
* @see org.springframework.scheduling.annotation.SchedulingConfigurer
*/
public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean {
private TaskScheduler taskScheduler;
private ScheduledExecutorService localExecutor;
private Map<Runnable, Trigger> triggerTasks;
private Map<Runnable, String> cronTasks;
private Map<Runnable, Long> fixedRateTasks;
private Map<Runnable, Long> fixedDelayTasks;
private final Set<ScheduledFuture<?>> scheduledFutures = new LinkedHashSet<ScheduledFuture<?>>();
/**
* Set the TaskScheduler to register scheduled tasks with.
*/
public void setTaskScheduler(TaskScheduler taskScheduler) {
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
this.taskScheduler = taskScheduler;
}
/**
* Set the {@link org.springframework.scheduling.TaskScheduler} to register scheduled
* tasks with, or a {@link java.util.concurrent.ScheduledExecutorService} to be
* wrapped as a TaskScheduler.
*/
public void setScheduler(Object scheduler) {
Assert.notNull(scheduler, "Scheduler object must not be null");
if (scheduler instanceof TaskScheduler) {
this.taskScheduler = (TaskScheduler) scheduler;
}
else if (scheduler instanceof ScheduledExecutorService) {
this.taskScheduler = new ConcurrentTaskScheduler(((ScheduledExecutorService) scheduler));
}
else {
throw new IllegalArgumentException("Unsupported scheduler type: " + scheduler.getClass());
}
}
/**
* Return the scheduler instance for this registrar (may be null)
*/
public TaskScheduler getScheduler() {
return this.taskScheduler;
}
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and Trigger objects
* (typically custom implementations of the {@link Trigger} interface).
*/
public void setTriggerTasks(Map<Runnable, Trigger> triggerTasks) {
this.triggerTasks = triggerTasks;
}
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and cron expressions.
* @see CronTrigger
*/
public void setCronTasks(Map<Runnable, String> cronTasks) {
this.cronTasks = cronTasks;
}
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-rate values.
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
*/
public void setFixedRateTasks(Map<Runnable, Long> fixedRateTasks) {
this.fixedRateTasks = fixedRateTasks;
}
/**
* Add a Runnable task to be triggered per the given {@link Trigger}.
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
*/
public void addTriggerTask(Runnable task, Trigger trigger) {
if (this.triggerTasks == null) {
this.triggerTasks = new HashMap<Runnable, Trigger>();
}
this.triggerTasks.put(task, trigger);
}
/**
* Add a Runnable task to be triggered per the given cron expression
*/
public void addCronTask(Runnable task, String cronExpression) {
if (this.cronTasks == null) {
this.cronTasks = new HashMap<Runnable, String>();
}
this.cronTasks.put(task, cronExpression);
}
/**
* Add a Runnable task to be triggered with the given fixed delay.
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
*/
public void addFixedDelayTask(Runnable task, long delay) {
if (this.fixedDelayTasks == null) {
this.fixedDelayTasks = new HashMap<Runnable, Long>();
}
this.fixedDelayTasks.put(task, delay);
}
/**
* Add a Runnable task to be triggered at the given fixed-rate period.
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
*/
public void addFixedRateTask(Runnable task, long period) {
if (this.fixedRateTasks == null) {
this.fixedRateTasks = new HashMap<Runnable, Long>();
}
this.fixedRateTasks.put(task, period);
}
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-delay values.
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
*/
public void setFixedDelayTasks(Map<Runnable, Long> fixedDelayTasks) {
this.fixedDelayTasks = fixedDelayTasks;
}
public void afterPropertiesSet() {
if (this.taskScheduler == null) {
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}
if (this.triggerTasks != null) {
for (Map.Entry<Runnable, Trigger> entry : this.triggerTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.schedule(entry.getKey(), entry.getValue()));
}
}
if (this.cronTasks != null) {
for (Map.Entry<Runnable, String> entry : this.cronTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.schedule(entry.getKey(), new CronTrigger(entry.getValue())));
}
}
if (this.fixedRateTasks != null) {
for (Map.Entry<Runnable, Long> entry : this.fixedRateTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(entry.getKey(), entry.getValue()));
}
}
if (this.fixedDelayTasks != null) {
for (Map.Entry<Runnable, Long> entry : this.fixedDelayTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(entry.getKey(), entry.getValue()));
}
}
}
public void destroy() {
for (ScheduledFuture<?> future : this.scheduledFutures) {
future.cancel(true);
}
if (this.localExecutor != null) {
this.localExecutor.shutdownNow();
}
}
}
/*
* Copyright 2002-2011 the original author 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 java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.scheduling.TaskScheduler;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.concurrent.ConcurrentTaskScheduler;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.util.Assert;
/**
* Helper bean for registering tasks with a {@link TaskScheduler},
* typically using cron expressions.
*
* <p>As of Spring 3.1, {@code ScheduledTaskRegistrar} has a more prominent user-facing
* role when used in conjunction with the @{@link
* org.springframework.scheduling.annotation.EnableAsync EnableAsync} annotation and its
* {@link org.springframework.scheduling.annotation.SchedulingConfigurer
* SchedulingConfigurer} callback interface.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.scheduling.annotation.EnableAsync
* @see org.springframework.scheduling.annotation.SchedulingConfigurer
*/
public class ScheduledTaskRegistrar implements InitializingBean, DisposableBean {
private TaskScheduler taskScheduler;
private ScheduledExecutorService localExecutor;
private Map<Runnable, Trigger> triggerTasks;
private Map<Runnable, String> cronTasks;
private Map<Runnable, Long> fixedRateTasks;
private Map<Runnable, Long> fixedDelayTasks;
private final Set<ScheduledFuture<?>> scheduledFutures = new LinkedHashSet<ScheduledFuture<?>>();
/**
* Set the TaskScheduler to register scheduled tasks with.
*/
public void setTaskScheduler(TaskScheduler taskScheduler) {
Assert.notNull(taskScheduler, "TaskScheduler must not be null");
this.taskScheduler = taskScheduler;
}
/**
* Set the {@link org.springframework.scheduling.TaskScheduler} to register scheduled
* tasks with, or a {@link java.util.concurrent.ScheduledExecutorService} to be
* wrapped as a TaskScheduler.
*/
public void setScheduler(Object scheduler) {
Assert.notNull(scheduler, "Scheduler object must not be null");
if (scheduler instanceof TaskScheduler) {
this.taskScheduler = (TaskScheduler) scheduler;
}
else if (scheduler instanceof ScheduledExecutorService) {
this.taskScheduler = new ConcurrentTaskScheduler(((ScheduledExecutorService) scheduler));
}
else {
throw new IllegalArgumentException("Unsupported scheduler type: " + scheduler.getClass());
}
}
/**
* Return the scheduler instance for this registrar (may be null)
*/
public TaskScheduler getScheduler() {
return this.taskScheduler;
}
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and Trigger objects
* (typically custom implementations of the {@link Trigger} interface).
*/
public void setTriggerTasks(Map<Runnable, Trigger> triggerTasks) {
this.triggerTasks = triggerTasks;
}
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and cron expressions.
* @see CronTrigger
*/
public void setCronTasks(Map<Runnable, String> cronTasks) {
this.cronTasks = cronTasks;
}
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-rate values.
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
*/
public void setFixedRateTasks(Map<Runnable, Long> fixedRateTasks) {
this.fixedRateTasks = fixedRateTasks;
}
/**
* Add a Runnable task to be triggered per the given {@link Trigger}.
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
*/
public void addTriggerTask(Runnable task, Trigger trigger) {
if (this.triggerTasks == null) {
this.triggerTasks = new HashMap<Runnable, Trigger>();
}
this.triggerTasks.put(task, trigger);
}
/**
* Add a Runnable task to be triggered per the given cron expression
*/
public void addCronTask(Runnable task, String cronExpression) {
if (this.cronTasks == null) {
this.cronTasks = new HashMap<Runnable, String>();
}
this.cronTasks.put(task, cronExpression);
}
/**
* Add a Runnable task to be triggered with the given fixed delay.
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
*/
public void addFixedDelayTask(Runnable task, long delay) {
if (this.fixedDelayTasks == null) {
this.fixedDelayTasks = new HashMap<Runnable, Long>();
}
this.fixedDelayTasks.put(task, delay);
}
/**
* Add a Runnable task to be triggered at the given fixed-rate period.
* @see TaskScheduler#scheduleAtFixedRate(Runnable, long)
*/
public void addFixedRateTask(Runnable task, long period) {
if (this.fixedRateTasks == null) {
this.fixedRateTasks = new HashMap<Runnable, Long>();
}
this.fixedRateTasks.put(task, period);
}
/**
* Specify triggered tasks as a Map of Runnables (the tasks) and fixed-delay values.
* @see TaskScheduler#scheduleWithFixedDelay(Runnable, long)
*/
public void setFixedDelayTasks(Map<Runnable, Long> fixedDelayTasks) {
this.fixedDelayTasks = fixedDelayTasks;
}
public void afterPropertiesSet() {
if (this.taskScheduler == null) {
this.localExecutor = Executors.newSingleThreadScheduledExecutor();
this.taskScheduler = new ConcurrentTaskScheduler(this.localExecutor);
}
if (this.triggerTasks != null) {
for (Map.Entry<Runnable, Trigger> entry : this.triggerTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.schedule(entry.getKey(), entry.getValue()));
}
}
if (this.cronTasks != null) {
for (Map.Entry<Runnable, String> entry : this.cronTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.schedule(entry.getKey(), new CronTrigger(entry.getValue())));
}
}
if (this.fixedRateTasks != null) {
for (Map.Entry<Runnable, Long> entry : this.fixedRateTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.scheduleAtFixedRate(entry.getKey(), entry.getValue()));
}
}
if (this.fixedDelayTasks != null) {
for (Map.Entry<Runnable, Long> entry : this.fixedDelayTasks.entrySet()) {
this.scheduledFutures.add(this.taskScheduler.scheduleWithFixedDelay(entry.getKey(), entry.getValue()));
}
}
}
public void destroy() {
for (ScheduledFuture<?> future : this.scheduledFutures) {
future.cancel(true);
}
if (this.localExecutor != null) {
this.localExecutor.shutdownNow();
}
}
}

View File

@@ -1,9 +1,9 @@
/**
*
* Support package for declarative scheduling configuration,
* with XML schema being the primary configuration format.
*
*/
package org.springframework.scheduling.config;
/**
*
* Support package for declarative scheduling configuration,
* with XML schema being the primary configuration format.
*
*/
package org.springframework.scheduling.config;

View File

@@ -1,92 +1,92 @@
/*
* Copyright 2002-2010 the original author 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.support;
import java.util.Date;
import java.util.TimeZone;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
/**
* {@link Trigger} implementation for cron expressions.
* Wraps a {@link CronSequenceGenerator}.
*
* @author Juergen Hoeller
* @since 3.0
* @see CronSequenceGenerator
*/
public class CronTrigger implements Trigger {
private final CronSequenceGenerator sequenceGenerator;
/**
* Build a {@link CronTrigger} from the pattern provided in the default time zone.
* @param cronExpression a space-separated list of time fields,
* following cron expression conventions
*/
public CronTrigger(String cronExpression) {
this(cronExpression, TimeZone.getDefault());
}
/**
* Build a {@link CronTrigger} from the pattern provided.
* @param cronExpression a space-separated list of time fields,
* following cron expression conventions
* @param timeZone a time zone in which the trigger times will be generated
*/
public CronTrigger(String cronExpression, TimeZone timeZone) {
this.sequenceGenerator = new CronSequenceGenerator(cronExpression, timeZone);
}
public Date nextExecutionTime(TriggerContext triggerContext) {
Date date = triggerContext.lastCompletionTime();
if (date != null) {
Date scheduled = triggerContext.lastScheduledExecutionTime();
if (scheduled != null && date.before(scheduled)) {
// Previous task apparently executed too early...
// Let's simply use the last calculated execution time then,
// in order to prevent accidental re-fires in the same second.
date = scheduled;
}
}
else {
date = new Date();
}
return this.sequenceGenerator.next(date);
}
@Override
public boolean equals(Object obj) {
return (this == obj || (obj instanceof CronTrigger &&
this.sequenceGenerator.equals(((CronTrigger) obj).sequenceGenerator)));
}
@Override
public int hashCode() {
return this.sequenceGenerator.hashCode();
}
@Override
public String toString() {
return sequenceGenerator.toString();
}
}
/*
* Copyright 2002-2010 the original author 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.support;
import java.util.Date;
import java.util.TimeZone;
import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;
/**
* {@link Trigger} implementation for cron expressions.
* Wraps a {@link CronSequenceGenerator}.
*
* @author Juergen Hoeller
* @since 3.0
* @see CronSequenceGenerator
*/
public class CronTrigger implements Trigger {
private final CronSequenceGenerator sequenceGenerator;
/**
* Build a {@link CronTrigger} from the pattern provided in the default time zone.
* @param cronExpression a space-separated list of time fields,
* following cron expression conventions
*/
public CronTrigger(String cronExpression) {
this(cronExpression, TimeZone.getDefault());
}
/**
* Build a {@link CronTrigger} from the pattern provided.
* @param cronExpression a space-separated list of time fields,
* following cron expression conventions
* @param timeZone a time zone in which the trigger times will be generated
*/
public CronTrigger(String cronExpression, TimeZone timeZone) {
this.sequenceGenerator = new CronSequenceGenerator(cronExpression, timeZone);
}
public Date nextExecutionTime(TriggerContext triggerContext) {
Date date = triggerContext.lastCompletionTime();
if (date != null) {
Date scheduled = triggerContext.lastScheduledExecutionTime();
if (scheduled != null && date.before(scheduled)) {
// Previous task apparently executed too early...
// Let's simply use the last calculated execution time then,
// in order to prevent accidental re-fires in the same second.
date = scheduled;
}
}
else {
date = new Date();
}
return this.sequenceGenerator.next(date);
}
@Override
public boolean equals(Object obj) {
return (this == obj || (obj instanceof CronTrigger &&
this.sequenceGenerator.equals(((CronTrigger) obj).sequenceGenerator)));
}
@Override
public int hashCode() {
return this.sequenceGenerator.hashCode();
}
@Override
public String toString() {
return sequenceGenerator.toString();
}
}

View File

@@ -1,74 +1,74 @@
/*
* Copyright 2002-2011 the original author 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.support;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import org.springframework.util.ReflectionUtils;
/**
* Variant of {@link MethodInvokingRunnable} meant to be used for processing
* of no-arg scheduled methods. Propagates user exceptions to the caller,
* assuming that an error strategy for Runnables is in place.
*
* @author Juergen Hoeller
* @since 3.0.6
* @see org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor
*/
public class ScheduledMethodRunnable implements Runnable {
private final Object target;
private final Method method;
public ScheduledMethodRunnable(Object target, Method method) {
this.target = target;
this.method = method;
}
public ScheduledMethodRunnable(Object target, String methodName) throws NoSuchMethodException {
this.target = target;
this.method = target.getClass().getMethod(methodName);
}
public Object getTarget() {
return this.target;
}
public Method getMethod() {
return this.method;
}
public void run() {
try {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(this.target);
}
catch (InvocationTargetException ex) {
ReflectionUtils.rethrowRuntimeException(ex.getTargetException());
}
catch (IllegalAccessException ex) {
throw new UndeclaredThrowableException(ex);
}
}
}
/*
* Copyright 2002-2011 the original author 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.support;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import org.springframework.util.ReflectionUtils;
/**
* Variant of {@link MethodInvokingRunnable} meant to be used for processing
* of no-arg scheduled methods. Propagates user exceptions to the caller,
* assuming that an error strategy for Runnables is in place.
*
* @author Juergen Hoeller
* @since 3.0.6
* @see org.springframework.scheduling.annotation.ScheduledAnnotationBeanPostProcessor
*/
public class ScheduledMethodRunnable implements Runnable {
private final Object target;
private final Method method;
public ScheduledMethodRunnable(Object target, Method method) {
this.target = target;
this.method = method;
}
public ScheduledMethodRunnable(Object target, String methodName) throws NoSuchMethodException {
this.target = target;
this.method = target.getClass().getMethod(methodName);
}
public Object getTarget() {
return this.target;
}
public Method getMethod() {
return this.method;
}
public void run() {
try {
ReflectionUtils.makeAccessible(this.method);
this.method.invoke(this.target);
}
catch (InvocationTargetException ex) {
ReflectionUtils.rethrowRuntimeException(ex.getTargetException());
}
catch (IllegalAccessException ex) {
throw new UndeclaredThrowableException(ex);
}
}
}

View File

@@ -1,63 +1,63 @@
/*
* Copyright 2002-2009 the original author 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.support;
import java.util.Date;
import org.springframework.scheduling.TriggerContext;
/**
* Simple data holder implementation of the {@link TriggerContext} interface.
*
* @author Juergen Hoeller
* @since 3.0
*/
public class SimpleTriggerContext implements TriggerContext {
private volatile Date lastScheduledExecutionTime;
private volatile Date lastActualExecutionTime;
private volatile Date lastCompletionTime;
/**
* Update this holder's state with the latest time values.
* @param lastScheduledExecutionTime last <i>scheduled</i> execution time
* @param lastActualExecutionTime last <i>actual</i> execution time
* @param lastCompletionTime last completion time
*/
public void update(Date lastScheduledExecutionTime, Date lastActualExecutionTime, Date lastCompletionTime) {
this.lastScheduledExecutionTime = lastScheduledExecutionTime;
this.lastActualExecutionTime = lastActualExecutionTime;
this.lastCompletionTime = lastCompletionTime;
}
public Date lastScheduledExecutionTime() {
return this.lastScheduledExecutionTime;
}
public Date lastActualExecutionTime() {
return this.lastActualExecutionTime;
}
public Date lastCompletionTime() {
return this.lastCompletionTime;
}
}
/*
* Copyright 2002-2009 the original author 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.support;
import java.util.Date;
import org.springframework.scheduling.TriggerContext;
/**
* Simple data holder implementation of the {@link TriggerContext} interface.
*
* @author Juergen Hoeller
* @since 3.0
*/
public class SimpleTriggerContext implements TriggerContext {
private volatile Date lastScheduledExecutionTime;
private volatile Date lastActualExecutionTime;
private volatile Date lastCompletionTime;
/**
* Update this holder's state with the latest time values.
* @param lastScheduledExecutionTime last <i>scheduled</i> execution time
* @param lastActualExecutionTime last <i>actual</i> execution time
* @param lastCompletionTime last completion time
*/
public void update(Date lastScheduledExecutionTime, Date lastActualExecutionTime, Date lastCompletionTime) {
this.lastScheduledExecutionTime = lastScheduledExecutionTime;
this.lastActualExecutionTime = lastActualExecutionTime;
this.lastCompletionTime = lastCompletionTime;
}
public Date lastScheduledExecutionTime() {
return this.lastScheduledExecutionTime;
}
public Date lastActualExecutionTime() {
return this.lastActualExecutionTime;
}
public Date lastCompletionTime() {
return this.lastCompletionTime;
}
}

View File

@@ -1,8 +1,8 @@
/**
* Support classes for annotation-based constraint evaluation,
* e.g. using a JSR-303 Bean Validation provider.
*
* <p>Provides an extended variant of JSR-303's <code>@Valid</code>,
* supporting the specification of validation groups.
*/
package org.springframework.validation.annotation;
/**
* Support classes for annotation-based constraint evaluation,
* e.g. using a JSR-303 Bean Validation provider.
*
* <p>Provides an extended variant of JSR-303's <code>@Valid</code>,
* supporting the specification of validation groups.
*/
package org.springframework.validation.annotation;

View File

@@ -1,117 +1,117 @@
/*
* Copyright 2002-2009 the original author 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.validation.beanvalidation;
import java.util.Iterator;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* Simple {@link BeanPostProcessor} that checks JSR-303 constraint annotations
* in Spring-managed beans, throwing an initialization exception in case of
* constraint violations right before calling the bean's init method (if any).
*
* @author Juergen Hoeller
* @since 3.0
*/
public class BeanValidationPostProcessor implements BeanPostProcessor, InitializingBean {
private Validator validator;
private boolean afterInitialization = false;
/**
* Set the JSR-303 Validator to delegate to for validating beans.
* <p>Default is the default ValidatorFactory's default Validator.
*/
public void setValidator(Validator validator) {
this.validator = validator;
}
/**
* Set the JSR-303 ValidatorFactory to delegate to for validating beans,
* using its default Validator.
* <p>Default is the default ValidatorFactory's default Validator.
* @see javax.validation.ValidatorFactory#getValidator()
*/
public void setValidatorFactory(ValidatorFactory validatorFactory) {
this.validator = validatorFactory.getValidator();
}
/**
* Choose whether to perform validation after bean initialization
* (i.e. after init methods) instead of before (which is the default).
* <p>Default is "false" (before initialization). Switch this to "true"
* (after initialization) if you would like to give init methods a chance
* to populate constrained fields before they get validated.
*/
public void setAfterInitialization(boolean afterInitialization) {
this.afterInitialization = afterInitialization;
}
public void afterPropertiesSet() {
if (this.validator == null) {
this.validator = Validation.buildDefaultValidatorFactory().getValidator();
}
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!this.afterInitialization) {
doValidate(bean);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (this.afterInitialization) {
doValidate(bean);
}
return bean;
}
/**
* Perform validation of the given bean.
* @param bean the bean instance to validate
* @see javax.validation.Validator#validate
*/
protected void doValidate(Object bean) {
Set<ConstraintViolation<Object>> result = this.validator.validate(bean);
if (!result.isEmpty()) {
StringBuilder sb = new StringBuilder("Bean state is invalid: ");
for (Iterator<ConstraintViolation<Object>> it = result.iterator(); it.hasNext();) {
ConstraintViolation<Object> violation = it.next();
sb.append(violation.getPropertyPath()).append(" - ").append(violation.getMessage());
if (it.hasNext()) {
sb.append("; ");
}
}
throw new BeanInitializationException(sb.toString());
}
}
}
/*
* Copyright 2002-2009 the original author 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.validation.beanvalidation;
import java.util.Iterator;
import java.util.Set;
import javax.validation.ConstraintViolation;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
/**
* Simple {@link BeanPostProcessor} that checks JSR-303 constraint annotations
* in Spring-managed beans, throwing an initialization exception in case of
* constraint violations right before calling the bean's init method (if any).
*
* @author Juergen Hoeller
* @since 3.0
*/
public class BeanValidationPostProcessor implements BeanPostProcessor, InitializingBean {
private Validator validator;
private boolean afterInitialization = false;
/**
* Set the JSR-303 Validator to delegate to for validating beans.
* <p>Default is the default ValidatorFactory's default Validator.
*/
public void setValidator(Validator validator) {
this.validator = validator;
}
/**
* Set the JSR-303 ValidatorFactory to delegate to for validating beans,
* using its default Validator.
* <p>Default is the default ValidatorFactory's default Validator.
* @see javax.validation.ValidatorFactory#getValidator()
*/
public void setValidatorFactory(ValidatorFactory validatorFactory) {
this.validator = validatorFactory.getValidator();
}
/**
* Choose whether to perform validation after bean initialization
* (i.e. after init methods) instead of before (which is the default).
* <p>Default is "false" (before initialization). Switch this to "true"
* (after initialization) if you would like to give init methods a chance
* to populate constrained fields before they get validated.
*/
public void setAfterInitialization(boolean afterInitialization) {
this.afterInitialization = afterInitialization;
}
public void afterPropertiesSet() {
if (this.validator == null) {
this.validator = Validation.buildDefaultValidatorFactory().getValidator();
}
}
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
if (!this.afterInitialization) {
doValidate(bean);
}
return bean;
}
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
if (this.afterInitialization) {
doValidate(bean);
}
return bean;
}
/**
* Perform validation of the given bean.
* @param bean the bean instance to validate
* @see javax.validation.Validator#validate
*/
protected void doValidate(Object bean) {
Set<ConstraintViolation<Object>> result = this.validator.validate(bean);
if (!result.isEmpty()) {
StringBuilder sb = new StringBuilder("Bean state is invalid: ");
for (Iterator<ConstraintViolation<Object>> it = result.iterator(); it.hasNext();) {
ConstraintViolation<Object> violation = it.next();
sb.append(violation.getPropertyPath()).append(" - ").append(violation.getMessage());
if (it.hasNext()) {
sb.append("; ");
}
}
throw new BeanInitializationException(sb.toString());
}
}
}

View File

@@ -1,86 +1,86 @@
/*
* Copyright 2002-2010 the original author 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.validation.beanvalidation;
import javax.validation.MessageInterpolator;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorContext;
import javax.validation.ValidatorFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* Configurable bean class that exposes a specific JSR-303 Validator
* through its original interface as well as through the Spring
* {@link org.springframework.validation.Validator} interface.
*
* @author Juergen Hoeller
* @since 3.0
*/
public class CustomValidatorBean extends SpringValidatorAdapter implements Validator, InitializingBean {
private ValidatorFactory validatorFactory;
private MessageInterpolator messageInterpolator;
private TraversableResolver traversableResolver;
/**
* Set the ValidatorFactory to obtain the target Validator from.
* <p>Default is {@link javax.validation.Validation#buildDefaultValidatorFactory()}.
*/
public void setValidatorFactory(ValidatorFactory validatorFactory) {
this.validatorFactory = validatorFactory;
}
/**
* Specify a custom MessageInterpolator to use for this Validator.
*/
public void setMessageInterpolator(MessageInterpolator messageInterpolator) {
this.messageInterpolator = messageInterpolator;
}
/**
* Specify a custom TraversableResolver to use for this Validator.
*/
public void setTraversableResolver(TraversableResolver traversableResolver) {
this.traversableResolver = traversableResolver;
}
public void afterPropertiesSet() {
if (this.validatorFactory == null) {
this.validatorFactory = Validation.buildDefaultValidatorFactory();
}
ValidatorContext validatorContext = this.validatorFactory.usingContext();
MessageInterpolator targetInterpolator = this.messageInterpolator;
if (targetInterpolator == null) {
targetInterpolator = this.validatorFactory.getMessageInterpolator();
}
validatorContext.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));
if (this.traversableResolver != null) {
validatorContext.traversableResolver(this.traversableResolver);
}
setTargetValidator(validatorContext.getValidator());
}
}
/*
* Copyright 2002-2010 the original author 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.validation.beanvalidation;
import javax.validation.MessageInterpolator;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorContext;
import javax.validation.ValidatorFactory;
import org.springframework.beans.factory.InitializingBean;
/**
* Configurable bean class that exposes a specific JSR-303 Validator
* through its original interface as well as through the Spring
* {@link org.springframework.validation.Validator} interface.
*
* @author Juergen Hoeller
* @since 3.0
*/
public class CustomValidatorBean extends SpringValidatorAdapter implements Validator, InitializingBean {
private ValidatorFactory validatorFactory;
private MessageInterpolator messageInterpolator;
private TraversableResolver traversableResolver;
/**
* Set the ValidatorFactory to obtain the target Validator from.
* <p>Default is {@link javax.validation.Validation#buildDefaultValidatorFactory()}.
*/
public void setValidatorFactory(ValidatorFactory validatorFactory) {
this.validatorFactory = validatorFactory;
}
/**
* Specify a custom MessageInterpolator to use for this Validator.
*/
public void setMessageInterpolator(MessageInterpolator messageInterpolator) {
this.messageInterpolator = messageInterpolator;
}
/**
* Specify a custom TraversableResolver to use for this Validator.
*/
public void setTraversableResolver(TraversableResolver traversableResolver) {
this.traversableResolver = traversableResolver;
}
public void afterPropertiesSet() {
if (this.validatorFactory == null) {
this.validatorFactory = Validation.buildDefaultValidatorFactory();
}
ValidatorContext validatorContext = this.validatorFactory.usingContext();
MessageInterpolator targetInterpolator = this.messageInterpolator;
if (targetInterpolator == null) {
targetInterpolator = this.validatorFactory.getMessageInterpolator();
}
validatorContext.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));
if (this.traversableResolver != null) {
validatorContext.traversableResolver(this.traversableResolver);
}
setTargetValidator(validatorContext.getValidator());
}
}

View File

@@ -1,257 +1,257 @@
/*
* Copyright 2002-2010 the original author 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.validation.beanvalidation;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.validation.Configuration;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.MessageInterpolator;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorContext;
import javax.validation.ValidatorFactory;
import javax.validation.spi.ValidationProvider;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.MessageSource;
import org.springframework.core.io.Resource;
import org.springframework.util.CollectionUtils;
/**
* This is the central class for <code>javax.validation</code> (JSR-303) setup
* in a Spring application context: It bootstraps a <code>javax.validation.ValidationFactory</code>
* and exposes it through the Spring {@link org.springframework.validation.Validator} interface
* as well as through the JSR-303 {@link javax.validation.Validator} interface and the
* {@link javax.validation.ValidatorFactory} interface itself.
*
* <p>When talking to an instance of this bean through the Spring or JSR-303 Validator interfaces,
* you'll be talking to the default Validator of the underlying ValidatorFactory. This is very
* convenient in that you don't have to perform yet another call on the factory, assuming that
* you will almost always use the default Validator anyway. This can also be injected directly
* into any target dependency of type {@link org.springframework.validation.Validator}!
*
* @author Juergen Hoeller
* @since 3.0
* @see javax.validation.ValidatorFactory
* @see javax.validation.Validator
* @see javax.validation.Validation#buildDefaultValidatorFactory()
* @see javax.validation.ValidatorFactory#getValidator()
*/
public class LocalValidatorFactoryBean extends SpringValidatorAdapter
implements ValidatorFactory, ApplicationContextAware, InitializingBean {
@SuppressWarnings("rawtypes")
private Class providerClass;
private MessageInterpolator messageInterpolator;
private TraversableResolver traversableResolver;
private ConstraintValidatorFactory constraintValidatorFactory;
private Resource[] mappingLocations;
private final Map<String, String> validationPropertyMap = new HashMap<String, String>();
private ApplicationContext applicationContext;
private ValidatorFactory validatorFactory;
/**
* Specify the desired provider class, if any.
* <p>If not specified, JSR-303's default search mechanism will be used.
* @see javax.validation.Validation#byProvider(Class)
* @see javax.validation.Validation#byDefaultProvider()
*/
@SuppressWarnings("rawtypes")
public void setProviderClass(Class<? extends ValidationProvider> providerClass) {
this.providerClass = providerClass;
}
/**
* Specify a custom MessageInterpolator to use for this ValidatorFactory
* and its exposed default Validator.
*/
public void setMessageInterpolator(MessageInterpolator messageInterpolator) {
this.messageInterpolator = messageInterpolator;
}
/**
* Specify a custom Spring MessageSource for resolving validation messages,
* instead of relying on JSR-303's default "ValidationMessages.properties" bundle
* in the classpath. This may refer to a Spring context's shared "messageSource" bean,
* or to some special MessageSource setup for validation purposes only.
* <p><b>NOTE:</b> This feature requires Hibernate Validator 4.1 or higher on the classpath.
* You may nevertheless use a different validation provider but Hibernate Validator's
* {@link ResourceBundleMessageInterpolator} class must be accessible during configuration.
* <p>Specify either this property or {@link #setMessageInterpolator "messageInterpolator"},
* not both. If you would like to build a custom MessageInterpolator, consider deriving from
* Hibernate Validator's {@link ResourceBundleMessageInterpolator} and passing in a
* Spring {@link MessageSourceResourceBundleLocator} when constructing your interpolator.
* @see ResourceBundleMessageInterpolator
* @see MessageSourceResourceBundleLocator
*/
public void setValidationMessageSource(MessageSource messageSource) {
this.messageInterpolator = HibernateValidatorDelegate.buildMessageInterpolator(messageSource);
}
/**
* Specify a custom TraversableResolver to use for this ValidatorFactory
* and its exposed default Validator.
*/
public void setTraversableResolver(TraversableResolver traversableResolver) {
this.traversableResolver = traversableResolver;
}
/**
* Specify a custom ConstraintValidatorFactory to use for this ValidatorFactory.
* <p>Default is a {@link SpringConstraintValidatorFactory}, delegating to the
* containing ApplicationContext for creating autowired ConstraintValidator instances.
*/
public void setConstraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
this.constraintValidatorFactory = constraintValidatorFactory;
}
/**
* Specify resource locations to load XML constraint mapping files from, if any.
*/
public void setMappingLocations(Resource[] mappingLocations) {
this.mappingLocations = mappingLocations;
}
/**
* Specify bean validation properties to be passed to the validation provider.
* <p>Can be populated with a String "value" (parsed via PropertiesEditor)
* or a "props" element in XML bean definitions.
* @see javax.validation.Configuration#addProperty(String, String)
*/
public void setValidationProperties(Properties jpaProperties) {
CollectionUtils.mergePropertiesIntoMap(jpaProperties, this.validationPropertyMap);
}
/**
* Specify bean validation properties to be passed to the validation provider as a Map.
* <p>Can be populated with a "map" or "props" element in XML bean definitions.
* @see javax.validation.Configuration#addProperty(String, String)
*/
public void setValidationPropertyMap(Map<String, String> validationProperties) {
if (validationProperties != null) {
this.validationPropertyMap.putAll(validationProperties);
}
}
/**
* Allow Map access to the bean validation properties to be passed to the validation provider,
* with the option to add or override specific entries.
* <p>Useful for specifying entries directly, for example via "validationPropertyMap[myKey]".
*/
public Map<String, String> getValidationPropertyMap() {
return this.validationPropertyMap;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@SuppressWarnings("unchecked")
public void afterPropertiesSet() {
@SuppressWarnings("rawtypes")
Configuration configuration = (this.providerClass != null ?
Validation.byProvider(this.providerClass).configure() :
Validation.byDefaultProvider().configure());
MessageInterpolator targetInterpolator = this.messageInterpolator;
if (targetInterpolator == null) {
targetInterpolator = configuration.getDefaultMessageInterpolator();
}
configuration.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));
if (this.traversableResolver != null) {
configuration.traversableResolver(this.traversableResolver);
}
ConstraintValidatorFactory targetConstraintValidatorFactory = this.constraintValidatorFactory;
if (targetConstraintValidatorFactory == null && this.applicationContext != null) {
targetConstraintValidatorFactory =
new SpringConstraintValidatorFactory(this.applicationContext.getAutowireCapableBeanFactory());
}
if (targetConstraintValidatorFactory != null) {
configuration.constraintValidatorFactory(targetConstraintValidatorFactory);
}
if (this.mappingLocations != null) {
for (Resource location : this.mappingLocations) {
try {
configuration.addMapping(location.getInputStream());
}
catch (IOException ex) {
throw new IllegalStateException("Cannot read mapping resource: " + location);
}
}
}
for (Map.Entry<String, String> entry : this.validationPropertyMap.entrySet()) {
configuration.addProperty(entry.getKey(), entry.getValue());
}
this.validatorFactory = configuration.buildValidatorFactory();
setTargetValidator(this.validatorFactory.getValidator());
}
public Validator getValidator() {
return this.validatorFactory.getValidator();
}
public ValidatorContext usingContext() {
return this.validatorFactory.usingContext();
}
public MessageInterpolator getMessageInterpolator() {
return this.validatorFactory.getMessageInterpolator();
}
public TraversableResolver getTraversableResolver() {
return this.validatorFactory.getTraversableResolver();
}
public ConstraintValidatorFactory getConstraintValidatorFactory() {
return this.validatorFactory.getConstraintValidatorFactory();
}
/**
* Inner class to avoid a hard-coded Hibernate Validator 4.1 dependency.
*/
private static class HibernateValidatorDelegate {
public static MessageInterpolator buildMessageInterpolator(MessageSource messageSource) {
return new ResourceBundleMessageInterpolator(new MessageSourceResourceBundleLocator(messageSource));
}
}
}
/*
* Copyright 2002-2010 the original author 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.validation.beanvalidation;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.validation.Configuration;
import javax.validation.ConstraintValidatorFactory;
import javax.validation.MessageInterpolator;
import javax.validation.TraversableResolver;
import javax.validation.Validation;
import javax.validation.Validator;
import javax.validation.ValidatorContext;
import javax.validation.ValidatorFactory;
import javax.validation.spi.ValidationProvider;
import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.MessageSource;
import org.springframework.core.io.Resource;
import org.springframework.util.CollectionUtils;
/**
* This is the central class for <code>javax.validation</code> (JSR-303) setup
* in a Spring application context: It bootstraps a <code>javax.validation.ValidationFactory</code>
* and exposes it through the Spring {@link org.springframework.validation.Validator} interface
* as well as through the JSR-303 {@link javax.validation.Validator} interface and the
* {@link javax.validation.ValidatorFactory} interface itself.
*
* <p>When talking to an instance of this bean through the Spring or JSR-303 Validator interfaces,
* you'll be talking to the default Validator of the underlying ValidatorFactory. This is very
* convenient in that you don't have to perform yet another call on the factory, assuming that
* you will almost always use the default Validator anyway. This can also be injected directly
* into any target dependency of type {@link org.springframework.validation.Validator}!
*
* @author Juergen Hoeller
* @since 3.0
* @see javax.validation.ValidatorFactory
* @see javax.validation.Validator
* @see javax.validation.Validation#buildDefaultValidatorFactory()
* @see javax.validation.ValidatorFactory#getValidator()
*/
public class LocalValidatorFactoryBean extends SpringValidatorAdapter
implements ValidatorFactory, ApplicationContextAware, InitializingBean {
@SuppressWarnings("rawtypes")
private Class providerClass;
private MessageInterpolator messageInterpolator;
private TraversableResolver traversableResolver;
private ConstraintValidatorFactory constraintValidatorFactory;
private Resource[] mappingLocations;
private final Map<String, String> validationPropertyMap = new HashMap<String, String>();
private ApplicationContext applicationContext;
private ValidatorFactory validatorFactory;
/**
* Specify the desired provider class, if any.
* <p>If not specified, JSR-303's default search mechanism will be used.
* @see javax.validation.Validation#byProvider(Class)
* @see javax.validation.Validation#byDefaultProvider()
*/
@SuppressWarnings("rawtypes")
public void setProviderClass(Class<? extends ValidationProvider> providerClass) {
this.providerClass = providerClass;
}
/**
* Specify a custom MessageInterpolator to use for this ValidatorFactory
* and its exposed default Validator.
*/
public void setMessageInterpolator(MessageInterpolator messageInterpolator) {
this.messageInterpolator = messageInterpolator;
}
/**
* Specify a custom Spring MessageSource for resolving validation messages,
* instead of relying on JSR-303's default "ValidationMessages.properties" bundle
* in the classpath. This may refer to a Spring context's shared "messageSource" bean,
* or to some special MessageSource setup for validation purposes only.
* <p><b>NOTE:</b> This feature requires Hibernate Validator 4.1 or higher on the classpath.
* You may nevertheless use a different validation provider but Hibernate Validator's
* {@link ResourceBundleMessageInterpolator} class must be accessible during configuration.
* <p>Specify either this property or {@link #setMessageInterpolator "messageInterpolator"},
* not both. If you would like to build a custom MessageInterpolator, consider deriving from
* Hibernate Validator's {@link ResourceBundleMessageInterpolator} and passing in a
* Spring {@link MessageSourceResourceBundleLocator} when constructing your interpolator.
* @see ResourceBundleMessageInterpolator
* @see MessageSourceResourceBundleLocator
*/
public void setValidationMessageSource(MessageSource messageSource) {
this.messageInterpolator = HibernateValidatorDelegate.buildMessageInterpolator(messageSource);
}
/**
* Specify a custom TraversableResolver to use for this ValidatorFactory
* and its exposed default Validator.
*/
public void setTraversableResolver(TraversableResolver traversableResolver) {
this.traversableResolver = traversableResolver;
}
/**
* Specify a custom ConstraintValidatorFactory to use for this ValidatorFactory.
* <p>Default is a {@link SpringConstraintValidatorFactory}, delegating to the
* containing ApplicationContext for creating autowired ConstraintValidator instances.
*/
public void setConstraintValidatorFactory(ConstraintValidatorFactory constraintValidatorFactory) {
this.constraintValidatorFactory = constraintValidatorFactory;
}
/**
* Specify resource locations to load XML constraint mapping files from, if any.
*/
public void setMappingLocations(Resource[] mappingLocations) {
this.mappingLocations = mappingLocations;
}
/**
* Specify bean validation properties to be passed to the validation provider.
* <p>Can be populated with a String "value" (parsed via PropertiesEditor)
* or a "props" element in XML bean definitions.
* @see javax.validation.Configuration#addProperty(String, String)
*/
public void setValidationProperties(Properties jpaProperties) {
CollectionUtils.mergePropertiesIntoMap(jpaProperties, this.validationPropertyMap);
}
/**
* Specify bean validation properties to be passed to the validation provider as a Map.
* <p>Can be populated with a "map" or "props" element in XML bean definitions.
* @see javax.validation.Configuration#addProperty(String, String)
*/
public void setValidationPropertyMap(Map<String, String> validationProperties) {
if (validationProperties != null) {
this.validationPropertyMap.putAll(validationProperties);
}
}
/**
* Allow Map access to the bean validation properties to be passed to the validation provider,
* with the option to add or override specific entries.
* <p>Useful for specifying entries directly, for example via "validationPropertyMap[myKey]".
*/
public Map<String, String> getValidationPropertyMap() {
return this.validationPropertyMap;
}
public void setApplicationContext(ApplicationContext applicationContext) {
this.applicationContext = applicationContext;
}
@SuppressWarnings("unchecked")
public void afterPropertiesSet() {
@SuppressWarnings("rawtypes")
Configuration configuration = (this.providerClass != null ?
Validation.byProvider(this.providerClass).configure() :
Validation.byDefaultProvider().configure());
MessageInterpolator targetInterpolator = this.messageInterpolator;
if (targetInterpolator == null) {
targetInterpolator = configuration.getDefaultMessageInterpolator();
}
configuration.messageInterpolator(new LocaleContextMessageInterpolator(targetInterpolator));
if (this.traversableResolver != null) {
configuration.traversableResolver(this.traversableResolver);
}
ConstraintValidatorFactory targetConstraintValidatorFactory = this.constraintValidatorFactory;
if (targetConstraintValidatorFactory == null && this.applicationContext != null) {
targetConstraintValidatorFactory =
new SpringConstraintValidatorFactory(this.applicationContext.getAutowireCapableBeanFactory());
}
if (targetConstraintValidatorFactory != null) {
configuration.constraintValidatorFactory(targetConstraintValidatorFactory);
}
if (this.mappingLocations != null) {
for (Resource location : this.mappingLocations) {
try {
configuration.addMapping(location.getInputStream());
}
catch (IOException ex) {
throw new IllegalStateException("Cannot read mapping resource: " + location);
}
}
}
for (Map.Entry<String, String> entry : this.validationPropertyMap.entrySet()) {
configuration.addProperty(entry.getKey(), entry.getValue());
}
this.validatorFactory = configuration.buildValidatorFactory();
setTargetValidator(this.validatorFactory.getValidator());
}
public Validator getValidator() {
return this.validatorFactory.getValidator();
}
public ValidatorContext usingContext() {
return this.validatorFactory.usingContext();
}
public MessageInterpolator getMessageInterpolator() {
return this.validatorFactory.getMessageInterpolator();
}
public TraversableResolver getTraversableResolver() {
return this.validatorFactory.getTraversableResolver();
}
public ConstraintValidatorFactory getConstraintValidatorFactory() {
return this.validatorFactory.getConstraintValidatorFactory();
}
/**
* Inner class to avoid a hard-coded Hibernate Validator 4.1 dependency.
*/
private static class HibernateValidatorDelegate {
public static MessageInterpolator buildMessageInterpolator(MessageSource messageSource) {
return new ResourceBundleMessageInterpolator(new MessageSourceResourceBundleLocator(messageSource));
}
}
}

View File

@@ -1,56 +1,56 @@
/*
* Copyright 2002-2010 the original author 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.validation.beanvalidation;
import java.util.Locale;
import javax.validation.MessageInterpolator;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.util.Assert;
/**
* Delegates to a target {@link MessageInterpolator} implementation but enforces Spring's
* managed Locale. Typically used to wrap the validation provider's default interpolator.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.context.i18n.LocaleContextHolder#getLocale()
*/
public class LocaleContextMessageInterpolator implements MessageInterpolator {
private final MessageInterpolator targetInterpolator;
/**
* Create a new LocaleContextMessageInterpolator, wrapping the given target interpolator.
* @param targetInterpolator the target MessageInterpolator to wrap
*/
public LocaleContextMessageInterpolator(MessageInterpolator targetInterpolator) {
Assert.notNull(targetInterpolator, "Target MessageInterpolator must not be null");
this.targetInterpolator = targetInterpolator;
}
public String interpolate(String message, Context context) {
return this.targetInterpolator.interpolate(message, context, LocaleContextHolder.getLocale());
}
public String interpolate(String message, Context context, Locale locale) {
return this.targetInterpolator.interpolate(message, context, locale);
}
}
/*
* Copyright 2002-2010 the original author 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.validation.beanvalidation;
import java.util.Locale;
import javax.validation.MessageInterpolator;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.util.Assert;
/**
* Delegates to a target {@link MessageInterpolator} implementation but enforces Spring's
* managed Locale. Typically used to wrap the validation provider's default interpolator.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.context.i18n.LocaleContextHolder#getLocale()
*/
public class LocaleContextMessageInterpolator implements MessageInterpolator {
private final MessageInterpolator targetInterpolator;
/**
* Create a new LocaleContextMessageInterpolator, wrapping the given target interpolator.
* @param targetInterpolator the target MessageInterpolator to wrap
*/
public LocaleContextMessageInterpolator(MessageInterpolator targetInterpolator) {
Assert.notNull(targetInterpolator, "Target MessageInterpolator must not be null");
this.targetInterpolator = targetInterpolator;
}
public String interpolate(String message, Context context) {
return this.targetInterpolator.interpolate(message, context, LocaleContextHolder.getLocale());
}
public String interpolate(String message, Context context, Locale locale) {
return this.targetInterpolator.interpolate(message, context, locale);
}
}

View File

@@ -1,55 +1,55 @@
/*
* Copyright 2002-2010 the original author 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.validation.beanvalidation;
import java.util.Locale;
import java.util.ResourceBundle;
import org.hibernate.validator.resourceloading.ResourceBundleLocator;
import org.springframework.context.MessageSource;
import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.util.Assert;
/**
* Implementation of Hibernate Validator 4.1's {@link ResourceBundleLocator} interface,
* exposing a Spring {@link MessageSource} as localized {@link MessageSourceResourceBundle}.
*
* @author Juergen Hoeller
* @since 3.0.4
* @see ResourceBundleLocator
* @see MessageSource
* @see MessageSourceResourceBundle
*/
public class MessageSourceResourceBundleLocator implements ResourceBundleLocator {
private final MessageSource messageSource;
/**
* Build a MessageSourceResourceBundleLocator for the given MessageSource.
* @param messageSource the Spring MessageSource to wrap
*/
public MessageSourceResourceBundleLocator(MessageSource messageSource) {
Assert.notNull(messageSource, "MessageSource must not be null");
this.messageSource = messageSource;
}
public ResourceBundle getResourceBundle(Locale locale) {
return new MessageSourceResourceBundle(this.messageSource, locale);
}
}
/*
* Copyright 2002-2010 the original author 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.validation.beanvalidation;
import java.util.Locale;
import java.util.ResourceBundle;
import org.hibernate.validator.resourceloading.ResourceBundleLocator;
import org.springframework.context.MessageSource;
import org.springframework.context.support.MessageSourceResourceBundle;
import org.springframework.util.Assert;
/**
* Implementation of Hibernate Validator 4.1's {@link ResourceBundleLocator} interface,
* exposing a Spring {@link MessageSource} as localized {@link MessageSourceResourceBundle}.
*
* @author Juergen Hoeller
* @since 3.0.4
* @see ResourceBundleLocator
* @see MessageSource
* @see MessageSourceResourceBundle
*/
public class MessageSourceResourceBundleLocator implements ResourceBundleLocator {
private final MessageSource messageSource;
/**
* Build a MessageSourceResourceBundleLocator for the given MessageSource.
* @param messageSource the Spring MessageSource to wrap
*/
public MessageSourceResourceBundleLocator(MessageSource messageSource) {
Assert.notNull(messageSource, "MessageSource must not be null");
this.messageSource = messageSource;
}
public ResourceBundle getResourceBundle(Locale locale) {
return new MessageSourceResourceBundle(this.messageSource, locale);
}
}

View File

@@ -1,53 +1,53 @@
/*
* Copyright 2002-2009 the original author 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.validation.beanvalidation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.util.Assert;
/**
* JSR-303 {@link ConstraintValidatorFactory} implementation that delegates to a
* Spring BeanFactory for creating autowired {@link ConstraintValidator} instances.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#createBean(Class)
* @see org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory()
*/
public class SpringConstraintValidatorFactory implements ConstraintValidatorFactory {
private final AutowireCapableBeanFactory beanFactory;
/**
* Create a new SpringConstraintValidatorFactory for the given BeanFactory.
* @param beanFactory the target BeanFactory
*/
public SpringConstraintValidatorFactory(AutowireCapableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
}
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
return this.beanFactory.createBean(key);
}
}
/*
* Copyright 2002-2009 the original author 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.validation.beanvalidation;
import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorFactory;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.util.Assert;
/**
* JSR-303 {@link ConstraintValidatorFactory} implementation that delegates to a
* Spring BeanFactory for creating autowired {@link ConstraintValidator} instances.
*
* @author Juergen Hoeller
* @since 3.0
* @see org.springframework.beans.factory.config.AutowireCapableBeanFactory#createBean(Class)
* @see org.springframework.context.ApplicationContext#getAutowireCapableBeanFactory()
*/
public class SpringConstraintValidatorFactory implements ConstraintValidatorFactory {
private final AutowireCapableBeanFactory beanFactory;
/**
* Create a new SpringConstraintValidatorFactory for the given BeanFactory.
* @param beanFactory the target BeanFactory
*/
public SpringConstraintValidatorFactory(AutowireCapableBeanFactory beanFactory) {
Assert.notNull(beanFactory, "BeanFactory must not be null");
this.beanFactory = beanFactory;
}
public <T extends ConstraintValidator<?, ?>> T getInstance(Class<T> key) {
return this.beanFactory.createBean(key);
}
}

View File

@@ -1,216 +1,216 @@
/*
* Copyright 2002-2011 the original author 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.validation.beanvalidation;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.validation.ConstraintViolation;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
import org.springframework.beans.NotReadablePropertyException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.validation.SmartValidator;
/**
* Adapter that takes a JSR-303 <code>javax.validator.Validator</code>
* and exposes it as a Spring {@link org.springframework.validation.Validator}
* while also exposing the original JSR-303 Validator interface itself.
*
* <p>Can be used as a programmatic wrapper. Also serves as base class for
* {@link CustomValidatorBean} and {@link LocalValidatorFactoryBean}.
*
* @author Juergen Hoeller
* @since 3.0
*/
public class SpringValidatorAdapter implements SmartValidator, javax.validation.Validator {
private static final Set<String> internalAnnotationAttributes = new HashSet<String>(3);
static {
internalAnnotationAttributes.add("message");
internalAnnotationAttributes.add("groups");
internalAnnotationAttributes.add("payload");
}
private javax.validation.Validator targetValidator;
/**
* Create a new SpringValidatorAdapter for the given JSR-303 Validator.
* @param targetValidator the JSR-303 Validator to wrap
*/
public SpringValidatorAdapter(javax.validation.Validator targetValidator) {
Assert.notNull(targetValidator, "Target Validator must not be null");
this.targetValidator = targetValidator;
}
SpringValidatorAdapter() {
}
void setTargetValidator(javax.validation.Validator targetValidator) {
this.targetValidator = targetValidator;
}
//---------------------------------------------------------------------
// Implementation of Spring Validator interface
//---------------------------------------------------------------------
public boolean supports(Class<?> clazz) {
return true;
}
public void validate(Object target, Errors errors) {
processConstraintViolations(this.targetValidator.validate(target), errors);
}
public void validate(Object target, Errors errors, Object... validationHints) {
Set<Class> groups = new LinkedHashSet<Class>();
if (validationHints != null) {
for (Object hint : validationHints) {
if (hint instanceof Class) {
groups.add((Class) hint);
}
}
}
processConstraintViolations(this.targetValidator.validate(target, groups.toArray(new Class[groups.size()])), errors);
}
/**
* Process the given JSR-303 ConstraintViolations, adding corresponding errors to
* the provided Spring {@link Errors} object.
* @param violations the JSR-303 ConstraintViolation results
* @param errors the Spring errors object to register to
*/
protected void processConstraintViolations(Set<ConstraintViolation<Object>> violations, Errors errors) {
for (ConstraintViolation<Object> violation : violations) {
String field = violation.getPropertyPath().toString();
FieldError fieldError = errors.getFieldError(field);
if (fieldError == null || !fieldError.isBindingFailure()) {
try {
String errorCode = violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, violation.getConstraintDescriptor());
if (errors instanceof BindingResult) {
// can do custom FieldError registration with invalid value from ConstraintViolation,
// as necessary for Hibernate Validator compatibility (non-indexed set path in field)
BindingResult bindingResult = (BindingResult) errors;
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
String nestedField = bindingResult.getNestedPath() + field;
ObjectError error;
if ("".equals(nestedField)) {
error = new ObjectError(
errors.getObjectName(), errorCodes, errorArgs, violation.getMessage());
}
else {
Object invalidValue = violation.getInvalidValue();
if (!"".equals(field) && invalidValue == violation.getLeafBean()) {
// bean constraint with property path: retrieve the actual property value
invalidValue = bindingResult.getRawFieldValue(field);
}
error = new FieldError(
errors.getObjectName(), nestedField, invalidValue, false,
errorCodes, errorArgs, violation.getMessage());
}
bindingResult.addError(error);
}
else {
// got no BindingResult - can only do standard rejectValue call
// with automatic extraction of the current field value
errors.rejectValue(field, errorCode, errorArgs, violation.getMessage());
}
}
catch (NotReadablePropertyException ex) {
throw new IllegalStateException("JSR-303 validated property '" + field +
"' does not have a corresponding accessor for Spring data binding - " +
"check your DataBinder's configuration (bean property versus direct field access)", ex);
}
}
}
}
/**
* Return FieldError arguments for a validation error on the given field.
* Invoked for each violated constraint.
* <p>The default implementation returns a first argument indicating the field name
* (of type DefaultMessageSourceResolvable, with "objectName.field" and "field" as codes).
* Afterwards, it adds all actual constraint annotation attributes (i.e. excluding
* "message", "groups" and "payload") in alphabetical order of their attribute names.
* <p>Can be overridden to e.g. add further attributes from the constraint descriptor.
* @param objectName the name of the target object
* @param field the field that caused the binding error
* @param descriptor the JSR-303 constraint descriptor
* @return the Object array that represents the FieldError arguments
* @see org.springframework.validation.FieldError#getArguments
* @see org.springframework.context.support.DefaultMessageSourceResolvable
* @see org.springframework.validation.DefaultBindingErrorProcessor#getArgumentsForBindError
*/
protected Object[] getArgumentsForConstraint(String objectName, String field, ConstraintDescriptor<?> descriptor) {
List<Object> arguments = new LinkedList<Object>();
String[] codes = new String[] {objectName + Errors.NESTED_PATH_SEPARATOR + field, field};
arguments.add(new DefaultMessageSourceResolvable(codes, field));
// Using a TreeMap for alphabetical ordering of attribute names
Map<String, Object> attributesToExpose = new TreeMap<String, Object>();
for (Map.Entry<String, Object> entry : descriptor.getAttributes().entrySet()) {
String attributeName = entry.getKey();
Object attributeValue = entry.getValue();
if (!internalAnnotationAttributes.contains(attributeName)) {
attributesToExpose.put(attributeName, attributeValue);
}
}
arguments.addAll(attributesToExpose.values());
return arguments.toArray(new Object[arguments.size()]);
}
//---------------------------------------------------------------------
// Implementation of JSR-303 Validator interface
//---------------------------------------------------------------------
public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
return this.targetValidator.validate(object, groups);
}
public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) {
return this.targetValidator.validateProperty(object, propertyName, groups);
}
public <T> Set<ConstraintViolation<T>> validateValue(
Class<T> beanType, String propertyName, Object value, Class<?>... groups) {
return this.targetValidator.validateValue(beanType, propertyName, value, groups);
}
public BeanDescriptor getConstraintsForClass(Class<?> clazz) {
return this.targetValidator.getConstraintsForClass(clazz);
}
public <T> T unwrap(Class<T> type) {
return this.targetValidator.unwrap(type);
}
}
/*
* Copyright 2002-2011 the original author 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.validation.beanvalidation;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import javax.validation.ConstraintViolation;
import javax.validation.metadata.BeanDescriptor;
import javax.validation.metadata.ConstraintDescriptor;
import org.springframework.beans.NotReadablePropertyException;
import org.springframework.context.support.DefaultMessageSourceResolvable;
import org.springframework.util.Assert;
import org.springframework.validation.BindingResult;
import org.springframework.validation.Errors;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.validation.SmartValidator;
/**
* Adapter that takes a JSR-303 <code>javax.validator.Validator</code>
* and exposes it as a Spring {@link org.springframework.validation.Validator}
* while also exposing the original JSR-303 Validator interface itself.
*
* <p>Can be used as a programmatic wrapper. Also serves as base class for
* {@link CustomValidatorBean} and {@link LocalValidatorFactoryBean}.
*
* @author Juergen Hoeller
* @since 3.0
*/
public class SpringValidatorAdapter implements SmartValidator, javax.validation.Validator {
private static final Set<String> internalAnnotationAttributes = new HashSet<String>(3);
static {
internalAnnotationAttributes.add("message");
internalAnnotationAttributes.add("groups");
internalAnnotationAttributes.add("payload");
}
private javax.validation.Validator targetValidator;
/**
* Create a new SpringValidatorAdapter for the given JSR-303 Validator.
* @param targetValidator the JSR-303 Validator to wrap
*/
public SpringValidatorAdapter(javax.validation.Validator targetValidator) {
Assert.notNull(targetValidator, "Target Validator must not be null");
this.targetValidator = targetValidator;
}
SpringValidatorAdapter() {
}
void setTargetValidator(javax.validation.Validator targetValidator) {
this.targetValidator = targetValidator;
}
//---------------------------------------------------------------------
// Implementation of Spring Validator interface
//---------------------------------------------------------------------
public boolean supports(Class<?> clazz) {
return true;
}
public void validate(Object target, Errors errors) {
processConstraintViolations(this.targetValidator.validate(target), errors);
}
public void validate(Object target, Errors errors, Object... validationHints) {
Set<Class> groups = new LinkedHashSet<Class>();
if (validationHints != null) {
for (Object hint : validationHints) {
if (hint instanceof Class) {
groups.add((Class) hint);
}
}
}
processConstraintViolations(this.targetValidator.validate(target, groups.toArray(new Class[groups.size()])), errors);
}
/**
* Process the given JSR-303 ConstraintViolations, adding corresponding errors to
* the provided Spring {@link Errors} object.
* @param violations the JSR-303 ConstraintViolation results
* @param errors the Spring errors object to register to
*/
protected void processConstraintViolations(Set<ConstraintViolation<Object>> violations, Errors errors) {
for (ConstraintViolation<Object> violation : violations) {
String field = violation.getPropertyPath().toString();
FieldError fieldError = errors.getFieldError(field);
if (fieldError == null || !fieldError.isBindingFailure()) {
try {
String errorCode = violation.getConstraintDescriptor().getAnnotation().annotationType().getSimpleName();
Object[] errorArgs = getArgumentsForConstraint(errors.getObjectName(), field, violation.getConstraintDescriptor());
if (errors instanceof BindingResult) {
// can do custom FieldError registration with invalid value from ConstraintViolation,
// as necessary for Hibernate Validator compatibility (non-indexed set path in field)
BindingResult bindingResult = (BindingResult) errors;
String[] errorCodes = bindingResult.resolveMessageCodes(errorCode, field);
String nestedField = bindingResult.getNestedPath() + field;
ObjectError error;
if ("".equals(nestedField)) {
error = new ObjectError(
errors.getObjectName(), errorCodes, errorArgs, violation.getMessage());
}
else {
Object invalidValue = violation.getInvalidValue();
if (!"".equals(field) && invalidValue == violation.getLeafBean()) {
// bean constraint with property path: retrieve the actual property value
invalidValue = bindingResult.getRawFieldValue(field);
}
error = new FieldError(
errors.getObjectName(), nestedField, invalidValue, false,
errorCodes, errorArgs, violation.getMessage());
}
bindingResult.addError(error);
}
else {
// got no BindingResult - can only do standard rejectValue call
// with automatic extraction of the current field value
errors.rejectValue(field, errorCode, errorArgs, violation.getMessage());
}
}
catch (NotReadablePropertyException ex) {
throw new IllegalStateException("JSR-303 validated property '" + field +
"' does not have a corresponding accessor for Spring data binding - " +
"check your DataBinder's configuration (bean property versus direct field access)", ex);
}
}
}
}
/**
* Return FieldError arguments for a validation error on the given field.
* Invoked for each violated constraint.
* <p>The default implementation returns a first argument indicating the field name
* (of type DefaultMessageSourceResolvable, with "objectName.field" and "field" as codes).
* Afterwards, it adds all actual constraint annotation attributes (i.e. excluding
* "message", "groups" and "payload") in alphabetical order of their attribute names.
* <p>Can be overridden to e.g. add further attributes from the constraint descriptor.
* @param objectName the name of the target object
* @param field the field that caused the binding error
* @param descriptor the JSR-303 constraint descriptor
* @return the Object array that represents the FieldError arguments
* @see org.springframework.validation.FieldError#getArguments
* @see org.springframework.context.support.DefaultMessageSourceResolvable
* @see org.springframework.validation.DefaultBindingErrorProcessor#getArgumentsForBindError
*/
protected Object[] getArgumentsForConstraint(String objectName, String field, ConstraintDescriptor<?> descriptor) {
List<Object> arguments = new LinkedList<Object>();
String[] codes = new String[] {objectName + Errors.NESTED_PATH_SEPARATOR + field, field};
arguments.add(new DefaultMessageSourceResolvable(codes, field));
// Using a TreeMap for alphabetical ordering of attribute names
Map<String, Object> attributesToExpose = new TreeMap<String, Object>();
for (Map.Entry<String, Object> entry : descriptor.getAttributes().entrySet()) {
String attributeName = entry.getKey();
Object attributeValue = entry.getValue();
if (!internalAnnotationAttributes.contains(attributeName)) {
attributesToExpose.put(attributeName, attributeValue);
}
}
arguments.addAll(attributesToExpose.values());
return arguments.toArray(new Object[arguments.size()]);
}
//---------------------------------------------------------------------
// Implementation of JSR-303 Validator interface
//---------------------------------------------------------------------
public <T> Set<ConstraintViolation<T>> validate(T object, Class<?>... groups) {
return this.targetValidator.validate(object, groups);
}
public <T> Set<ConstraintViolation<T>> validateProperty(T object, String propertyName, Class<?>... groups) {
return this.targetValidator.validateProperty(object, propertyName, groups);
}
public <T> Set<ConstraintViolation<T>> validateValue(
Class<T> beanType, String propertyName, Object value, Class<?>... groups) {
return this.targetValidator.validateValue(beanType, propertyName, value, groups);
}
public BeanDescriptor getConstraintsForClass(Class<?> clazz) {
return this.targetValidator.getConstraintsForClass(clazz);
}
public <T> T unwrap(Class<T> type) {
return this.targetValidator.unwrap(type);
}
}

View File

@@ -1,11 +1,11 @@
/**
* Support classes for integrating a JSR-303 Bean Validation provider
* (such as Hibernate Validator 4.0) into a Spring ApplicationContext
* and in particular with Spring's data binding and validation APIs.
*
* <p>The central class is {@link
* org.springframework.validation.beanvalidation.LocalValidatorFactoryBean}
* which defines a shared ValidatorFactory/Validator setup for availability
* to other Spring components.
*/
package org.springframework.validation.beanvalidation;
/**
* Support classes for integrating a JSR-303 Bean Validation provider
* (such as Hibernate Validator 4.0) into a Spring ApplicationContext
* and in particular with Spring's data binding and validation APIs.
*
* <p>The central class is {@link
* org.springframework.validation.beanvalidation.LocalValidatorFactoryBean}
* which defines a shared ValidatorFactory/Validator setup for availability
* to other Spring components.
*/
package org.springframework.validation.beanvalidation;