Merge branch '3.2.x' into cleanup-3.2.x
* 3.2.x: (111 commits) Fix FreeMarker form checbox macro generated names Fix DefaultMockMvcBuilder fluent API generic type Catch IAE when parsing content type Update @RequestParam javadoc Fix AntPathMatcher rule for combining with extensions DefaultLobHandler etc Minor javadoc updates Deprecated OracleLobHandler in favor of DefaultLobHandler for the Oracle 10g driver and higher Added "createTemporaryLob" flag to DefaultLobHandler, using JDBC 4.0's createBlob/Clob mechanism Add Castor XSD information to reference docs Do not use Servlet 3.0 API in doOptions() Cache target type per bean definition and allow for specifying it in advance Mentioning JDBC 4's unwrap method for obtaining the native connection now LazyConnectionDataSourceProxy catches setReadOnly exception analogous to DataSourceUtils Refined predictBeanType's typesToMatch check for FactoryBeans Fix minor javadoc typos Fix incorrect closing <web-app> tag in MVC docs Fixed minor typo Suppress warnings for resource leaks Update spring-test re: deprecated queryForInt() ...
This commit is contained in:
@@ -4,7 +4,7 @@ buildscript {
|
||||
}
|
||||
dependencies {
|
||||
classpath("org.springframework.build.gradle:propdeps-plugin:0.0.3")
|
||||
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.4")
|
||||
classpath("org.springframework.build.gradle:docbook-reference-plugin:0.2.6")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ configure(allprojects) { project ->
|
||||
group = "org.springframework"
|
||||
version = qualifyVersionIfNecessary(version)
|
||||
|
||||
ext.aspectjVersion = "1.7.1"
|
||||
ext.aspectjVersion = "1.7.2"
|
||||
ext.easymockVersion = "2.5.2"
|
||||
ext.hsqldbVersion = "1.8.0.10"
|
||||
ext.junitVersion = "4.11"
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -110,7 +110,7 @@ class MergePlugin implements Plugin<Project> {
|
||||
|
||||
// update 'into' project artifacts to contain the source artifact contents
|
||||
project.merge.into.sourcesJar.from(project.sourcesJar.source)
|
||||
project.merge.into.jar.from(project.jar.source)
|
||||
project.merge.into.jar.from(project.sourceSets.main.output)
|
||||
project.merge.into.javadoc {
|
||||
source += project.javadoc.source
|
||||
classpath += project.javadoc.classpath
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,8 +17,8 @@
|
||||
package org.springframework.aop.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
@@ -45,7 +45,7 @@ import org.springframework.util.StringUtils;
|
||||
*/
|
||||
public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
|
||||
private final Map<Method, AsyncTaskExecutor> executors = new HashMap<Method, AsyncTaskExecutor>();
|
||||
private final Map<Method, AsyncTaskExecutor> executors = new ConcurrentHashMap<Method, AsyncTaskExecutor>(16);
|
||||
|
||||
private Executor defaultExecutor;
|
||||
|
||||
@@ -59,7 +59,7 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
* @param defaultExecutor the executor to use when executing asynchronous methods
|
||||
*/
|
||||
public AsyncExecutionAspectSupport(Executor defaultExecutor) {
|
||||
this.setExecutor(defaultExecutor);
|
||||
this.defaultExecutor = defaultExecutor;
|
||||
}
|
||||
|
||||
|
||||
@@ -90,24 +90,25 @@ public abstract class AsyncExecutionAspectSupport implements BeanFactoryAware {
|
||||
* @return the executor to use (never {@code null})
|
||||
*/
|
||||
protected AsyncTaskExecutor determineAsyncExecutor(Method method) {
|
||||
if (!this.executors.containsKey(method)) {
|
||||
Executor executor = this.defaultExecutor;
|
||||
AsyncTaskExecutor executor = this.executors.get(method);
|
||||
if (executor == null) {
|
||||
Executor executorToUse = this.defaultExecutor;
|
||||
String qualifier = getExecutorQualifier(method);
|
||||
if (StringUtils.hasLength(qualifier)) {
|
||||
Assert.notNull(this.beanFactory,
|
||||
"BeanFactory must be set on " + this.getClass().getSimpleName() +
|
||||
" to access qualified executor [" + qualifier + "]");
|
||||
executor = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
|
||||
Assert.notNull(this.beanFactory, "BeanFactory must be set on " + getClass().getSimpleName() +
|
||||
" to access qualified executor '" + qualifier + "'");
|
||||
executorToUse = BeanFactoryAnnotationUtils.qualifiedBeanOfType(
|
||||
this.beanFactory, Executor.class, qualifier);
|
||||
}
|
||||
if (executor instanceof AsyncTaskExecutor) {
|
||||
this.executors.put(method, (AsyncTaskExecutor) executor);
|
||||
}
|
||||
else if (executor != null) {
|
||||
this.executors.put(method, new TaskExecutorAdapter(executor));
|
||||
else if (executorToUse == null) {
|
||||
throw new IllegalStateException("No executor qualifier specified and no default executor set on " +
|
||||
getClass().getSimpleName() + " either");
|
||||
}
|
||||
executor = (executorToUse instanceof AsyncTaskExecutor ?
|
||||
(AsyncTaskExecutor) executorToUse : new TaskExecutorAdapter(executorToUse));
|
||||
this.executors.put(method, executor);
|
||||
}
|
||||
return this.executors.get(method);
|
||||
return executor;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.aop.interceptor;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Future;
|
||||
@@ -25,8 +24,11 @@ import java.util.concurrent.Future;
|
||||
import org.aopalliance.intercept.MethodInterceptor;
|
||||
import org.aopalliance.intercept.MethodInvocation;
|
||||
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.Ordered;
|
||||
import org.springframework.core.task.AsyncTaskExecutor;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
@@ -76,7 +78,11 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
|
||||
* otherwise.
|
||||
*/
|
||||
public Object invoke(final MethodInvocation invocation) throws Throwable {
|
||||
Future<?> result = this.determineAsyncExecutor(invocation.getMethod()).submit(
|
||||
Class<?> targetClass = (invocation.getThis() != null ? AopUtils.getTargetClass(invocation.getThis()) : null);
|
||||
Method specificMethod = ClassUtils.getMostSpecificMethod(invocation.getMethod(), targetClass);
|
||||
specificMethod = BridgeMethodResolver.findBridgedMethod(specificMethod);
|
||||
|
||||
Future<?> result = determineAsyncExecutor(specificMethod).submit(
|
||||
new Callable<Object>() {
|
||||
public Object call() throws Exception {
|
||||
try {
|
||||
@@ -91,6 +97,7 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
if (Future.class.isAssignableFrom(invocation.getMethod().getReturnType())) {
|
||||
return result;
|
||||
}
|
||||
@@ -100,10 +107,9 @@ public class AsyncExecutionInterceptor extends AsyncExecutionAspectSupport
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* <p>This implementation is a no-op for compatibility in Spring 3.1.2. Subclasses may
|
||||
* override to provide support for extracting qualifier information, e.g. via an
|
||||
* annotation on the given method.
|
||||
* This implementation is a no-op for compatibility in Spring 3.1.2.
|
||||
* Subclasses may override to provide support for extracting qualifier information,
|
||||
* e.g. via an annotation on the given method.
|
||||
* @return always {@code null}
|
||||
* @see #determineAsyncExecutor(Method)
|
||||
* @since 3.1.2
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
|
||||
package org.springframework.beans.factory.aspectj;
|
||||
|
||||
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
@@ -23,12 +23,12 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
* Abstract superaspect for AspectJ aspects that can perform Dependency
|
||||
* Injection on objects, however they may be created. Define the beanCreation()
|
||||
* pointcut in subaspects.
|
||||
*
|
||||
*
|
||||
* <p>Subaspects may also need a metadata resolution strategy, in the
|
||||
* <code>BeanWiringInfoResolver</code> interface. The default implementation
|
||||
* {@code BeanWiringInfoResolver} interface. The default implementation
|
||||
* looks for a bean with the same name as the FQN. This is the default name
|
||||
* of a bean in a Spring container if the id value is not supplied explicitly.
|
||||
*
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Rod Johnson
|
||||
* @author Adrian Colyer
|
||||
@@ -62,7 +62,7 @@ public abstract aspect AbstractBeanConfigurerAspect extends BeanConfigurerSuppor
|
||||
|
||||
/**
|
||||
* The initialization of a new object.
|
||||
*
|
||||
*
|
||||
* <p>WARNING: Although this pointcut is non-abstract for backwards
|
||||
* compatibility reasons, it is meant to be overridden to select
|
||||
* initialization of any configurable bean.
|
||||
|
||||
@@ -17,11 +17,12 @@
|
||||
package org.springframework.beans.factory.aspectj;
|
||||
|
||||
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
import org.aspectj.lang.annotation.control.CodeGenerationHint;
|
||||
|
||||
/**
|
||||
* Abstract base aspect that can perform Dependency
|
||||
* Injection on objects, however they may be created.
|
||||
*
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.5.2
|
||||
*/
|
||||
@@ -29,28 +30,29 @@ public abstract aspect AbstractDependencyInjectionAspect {
|
||||
/**
|
||||
* Select construction join points for objects to inject dependencies
|
||||
*/
|
||||
public abstract pointcut beanConstruction(Object bean);
|
||||
public abstract pointcut beanConstruction(Object bean);
|
||||
|
||||
/**
|
||||
* Select deserialization join points for objects to inject dependencies
|
||||
*/
|
||||
public abstract pointcut beanDeserialization(Object bean);
|
||||
|
||||
|
||||
/**
|
||||
* Select join points in a configurable bean
|
||||
*/
|
||||
public abstract pointcut inConfigurableBean();
|
||||
|
||||
|
||||
/**
|
||||
* Select join points in beans to be configured prior to construction?
|
||||
* By default, use post-construction injection matching the default in the Configurable annotation.
|
||||
*/
|
||||
public pointcut preConstructionConfiguration() : if(false);
|
||||
|
||||
|
||||
/**
|
||||
* Select the most-specific initialization join point
|
||||
* Select the most-specific initialization join point
|
||||
* (most concrete class) for the initialization of an instance.
|
||||
*/
|
||||
@CodeGenerationHint(ifNameSuffix="6f1")
|
||||
public pointcut mostSpecificSubTypeConstruction() :
|
||||
if(thisJoinPoint.getSignature().getDeclaringType() == thisJoinPoint.getThis().getClass());
|
||||
|
||||
@@ -58,25 +60,25 @@ public abstract aspect AbstractDependencyInjectionAspect {
|
||||
* Select least specific super type that is marked for DI (so that injection occurs only once with pre-construction inejection
|
||||
*/
|
||||
public abstract pointcut leastSpecificSuperTypeConstruction();
|
||||
|
||||
|
||||
/**
|
||||
* Configure the bean
|
||||
*/
|
||||
public abstract void configureBean(Object bean);
|
||||
|
||||
|
||||
private pointcut preConstructionCondition() :
|
||||
|
||||
private pointcut preConstructionCondition() :
|
||||
leastSpecificSuperTypeConstruction() && preConstructionConfiguration();
|
||||
|
||||
|
||||
private pointcut postConstructionCondition() :
|
||||
mostSpecificSubTypeConstruction() && !preConstructionConfiguration();
|
||||
|
||||
|
||||
/**
|
||||
* Pre-construction configuration.
|
||||
*/
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
before(Object bean) :
|
||||
beanConstruction(bean) && preConstructionCondition() && inConfigurableBean() {
|
||||
before(Object bean) :
|
||||
beanConstruction(bean) && preConstructionCondition() && inConfigurableBean() {
|
||||
configureBean(bean);
|
||||
}
|
||||
|
||||
@@ -84,18 +86,18 @@ public abstract aspect AbstractDependencyInjectionAspect {
|
||||
* Post-construction configuration.
|
||||
*/
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object bean) returning :
|
||||
after(Object bean) returning :
|
||||
beanConstruction(bean) && postConstructionCondition() && inConfigurableBean() {
|
||||
configureBean(bean);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Post-deserialization configuration.
|
||||
*/
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object bean) returning :
|
||||
after(Object bean) returning :
|
||||
beanDeserialization(bean) && inConfigurableBean() {
|
||||
configureBean(bean);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -26,36 +26,36 @@ import java.io.Serializable;
|
||||
* upon deserialization. Subaspects need to simply provide definition for the configureBean() method. This
|
||||
* method may be implemented without relying on Spring container if so desired.
|
||||
* </p>
|
||||
* <p>
|
||||
* <p>
|
||||
* There are two cases that needs to be handled:
|
||||
* <ol>
|
||||
* <li>Normal object creation via the '<code>new</code>' operator: this is
|
||||
* taken care of by advising <code>initialization()</code> join points.</li>
|
||||
* <li>Normal object creation via the '{@code new}' operator: this is
|
||||
* taken care of by advising {@code initialization()} join points.</li>
|
||||
* <li>Object creation through deserialization: since no constructor is
|
||||
* invoked during deserialization, the aspect needs to advise a method that a
|
||||
* deserialization mechanism is going to invoke. Ideally, we should not
|
||||
* require user classes to implement any specific method. This implies that
|
||||
* we need to <i>introduce</i> the chosen method. We should also handle the cases
|
||||
* where the chosen method is already implemented in classes (in which case,
|
||||
* the user's implementation for that method should take precedence over the
|
||||
* the user's implementation for that method should take precedence over the
|
||||
* introduced implementation). There are a few choices for the chosen method:
|
||||
* <ul>
|
||||
* <li>readObject(ObjectOutputStream): Java requires that the method must be
|
||||
* <code>private</p>. Since aspects cannot introduce a private member,
|
||||
* {@code private}</p>. Since aspects cannot introduce a private member,
|
||||
* while preserving its name, this option is ruled out.</li>
|
||||
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
|
||||
* Problem solved! There is one (minor) limitation of this approach in
|
||||
* that if a user class already has this method, that method must be
|
||||
* <code>public</code>. However, this shouldn't be a big burden, since
|
||||
* use cases that need classes to implement readResolve() (custom enums,
|
||||
* <li>readResolve(): Java doesn't pose any restriction on an access specifier.
|
||||
* Problem solved! There is one (minor) limitation of this approach in
|
||||
* that if a user class already has this method, that method must be
|
||||
* {@code public}. However, this shouldn't be a big burden, since
|
||||
* use cases that need classes to implement readResolve() (custom enums,
|
||||
* for example) are unlikely to be marked as @Configurable, and
|
||||
* in any case asking to make that method <code>public</code> should not
|
||||
* in any case asking to make that method {@code public} should not
|
||||
* pose any undue burden.</li>
|
||||
* </ul>
|
||||
* The minor collaboration needed by user classes (i.e., that the
|
||||
* implementation of <code>readResolve()</code>, if any, must be
|
||||
* <code>public</code>) can be lifted as well if we were to use an
|
||||
* experimental feature in AspectJ - the <code>hasmethod()</code> PCD.</li>
|
||||
* The minor collaboration needed by user classes (i.e., that the
|
||||
* implementation of {@code readResolve()}, if any, must be
|
||||
* {@code public}) can be lifted as well if we were to use an
|
||||
* experimental feature in AspectJ - the {@code hasmethod()} PCD.</li>
|
||||
* </ol>
|
||||
|
||||
* <p>
|
||||
@@ -63,7 +63,7 @@ import java.io.Serializable;
|
||||
* is to use a 'declare parents' statement another aspect (a subaspect of this aspect would be a logical choice)
|
||||
* that declares the classes that need to be configured by supplying the {@link ConfigurableObject} interface.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* @author Ramnivas Laddad
|
||||
* @since 2.5.2
|
||||
*/
|
||||
@@ -71,8 +71,8 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
|
||||
/**
|
||||
* Select initialization join point as object construction
|
||||
*/
|
||||
public pointcut beanConstruction(Object bean) :
|
||||
initialization(ConfigurableObject+.new(..)) && this(bean);
|
||||
public pointcut beanConstruction(Object bean) :
|
||||
initialization(ConfigurableObject+.new(..)) && this(bean);
|
||||
|
||||
/**
|
||||
* Select deserialization join point made available through ITDs for ConfigurableDeserializationSupport
|
||||
@@ -80,40 +80,40 @@ public abstract aspect AbstractInterfaceDrivenDependencyInjectionAspect extends
|
||||
public pointcut beanDeserialization(Object bean) :
|
||||
execution(Object ConfigurableDeserializationSupport+.readResolve()) &&
|
||||
this(bean);
|
||||
|
||||
|
||||
public pointcut leastSpecificSuperTypeConstruction() : initialization(ConfigurableObject.new(..));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// Implementation to support re-injecting dependencies once an object is deserialized
|
||||
/**
|
||||
* Declare any class implementing Serializable and ConfigurableObject as also implementing
|
||||
* ConfigurableDeserializationSupport. This allows us to introduce the readResolve()
|
||||
* Declare any class implementing Serializable and ConfigurableObject as also implementing
|
||||
* ConfigurableDeserializationSupport. This allows us to introduce the readResolve()
|
||||
* method and select it with the beanDeserialization() pointcut.
|
||||
*
|
||||
*
|
||||
* <p>Here is an improved version that uses the hasmethod() pointcut and lifts
|
||||
* even the minor requirement on user classes:
|
||||
*
|
||||
* <pre class="code">declare parents: ConfigurableObject+ Serializable+
|
||||
* && !hasmethod(Object readResolve() throws ObjectStreamException)
|
||||
* && !hasmethod(Object readResolve() throws ObjectStreamException)
|
||||
* implements ConfigurableDeserializationSupport;
|
||||
* </pre>
|
||||
*/
|
||||
declare parents:
|
||||
declare parents:
|
||||
ConfigurableObject+ && Serializable+ implements ConfigurableDeserializationSupport;
|
||||
|
||||
|
||||
/**
|
||||
* A marker interface to which the <code>readResolve()</code> is introduced.
|
||||
* A marker interface to which the {@code readResolve()} is introduced.
|
||||
*/
|
||||
static interface ConfigurableDeserializationSupport extends Serializable {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Introduce the <code>readResolve()</code> method so that we can advise its
|
||||
* Introduce the {@code readResolve()} method so that we can advise its
|
||||
* execution to configure the object.
|
||||
*
|
||||
*
|
||||
* <p>Note if a method with the same signature already exists in a
|
||||
* <code>Serializable</code> class of ConfigurableObject type,
|
||||
* {@code Serializable} class of ConfigurableObject type,
|
||||
* that implementation will take precedence (a good thing, since we are
|
||||
* merely interested in an opportunity to detect deserialization.)
|
||||
*/
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.beans.factory.aspectj;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.aspectj.lang.annotation.control.CodeGenerationHint;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
@@ -32,7 +33,7 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
* annotation to identify which classes need autowiring.
|
||||
*
|
||||
* <p>The bean name to look up will be taken from the
|
||||
* <code>@Configurable</code> annotation if specified, otherwise the
|
||||
* {@code @Configurable} annotation if specified, otherwise the
|
||||
* default bean name to look up will be the FQN of the class being configured.
|
||||
*
|
||||
* @author Rod Johnson
|
||||
@@ -43,7 +44,7 @@ import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
* @see org.springframework.beans.factory.annotation.Configurable
|
||||
* @see org.springframework.beans.factory.annotation.AnnotationBeanWiringInfoResolver
|
||||
*/
|
||||
public aspect AnnotationBeanConfigurerAspect
|
||||
public aspect AnnotationBeanConfigurerAspect
|
||||
extends AbstractInterfaceDrivenDependencyInjectionAspect
|
||||
implements BeanFactoryAware, InitializingBean, DisposableBean {
|
||||
|
||||
@@ -51,7 +52,7 @@ public aspect AnnotationBeanConfigurerAspect
|
||||
|
||||
public pointcut inConfigurableBean() : @this(Configurable);
|
||||
|
||||
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
|
||||
public pointcut preConstructionConfiguration() : preConstructionConfigurationSupport(*);
|
||||
|
||||
declare parents: @Configurable * implements ConfigurableObject;
|
||||
|
||||
@@ -77,13 +78,14 @@ public aspect AnnotationBeanConfigurerAspect
|
||||
/*
|
||||
* An intermediary to match preConstructionConfiguration signature (that doesn't expose the annotation object)
|
||||
*/
|
||||
@CodeGenerationHint(ifNameSuffix="bb0")
|
||||
private pointcut preConstructionConfigurationSupport(Configurable c) : @this(c) && if(c.preConstruction());
|
||||
|
||||
/*
|
||||
* This declaration shouldn't be needed,
|
||||
* This declaration shouldn't be needed,
|
||||
* except for an AspectJ bug (https://bugs.eclipse.org/bugs/show_bug.cgi?id=214559)
|
||||
*/
|
||||
declare parents: @Configurable Serializable+
|
||||
declare parents: @Configurable Serializable+
|
||||
implements ConfigurableDeserializationSupport;
|
||||
|
||||
}
|
||||
|
||||
@@ -17,24 +17,24 @@ package org.springframework.beans.factory.aspectj;
|
||||
|
||||
/**
|
||||
* Generic-based dependency injection aspect.
|
||||
* <p>
|
||||
* This aspect allows users to implement efficient, type-safe dependency injection without
|
||||
* <p>
|
||||
* This aspect allows users to implement efficient, type-safe dependency injection without
|
||||
* the use of the @Configurable annotation.
|
||||
*
|
||||
* The subaspect of this aspect doesn't need to include any AOP constructs.
|
||||
* For example, here is a subaspect that configures the <code>PricingStrategyClient</code> objects.
|
||||
*
|
||||
* The subaspect of this aspect doesn't need to include any AOP constructs.
|
||||
* For example, here is a subaspect that configures the {@code PricingStrategyClient} objects.
|
||||
* <pre>
|
||||
* aspect PricingStrategyDependencyInjectionAspect
|
||||
* aspect PricingStrategyDependencyInjectionAspect
|
||||
* extends GenericInterfaceDrivenDependencyInjectionAspect<PricingStrategyClient> {
|
||||
* private PricingStrategy pricingStrategy;
|
||||
*
|
||||
* public void configure(PricingStrategyClient bean) {
|
||||
* bean.setPricingStrategy(pricingStrategy);
|
||||
*
|
||||
* public void configure(PricingStrategyClient bean) {
|
||||
* bean.setPricingStrategy(pricingStrategy);
|
||||
* }
|
||||
*
|
||||
* public void setPricingStrategy(PricingStrategy pricingStrategy) {
|
||||
* this.pricingStrategy = pricingStrategy;
|
||||
* }
|
||||
*
|
||||
* public void setPricingStrategy(PricingStrategy pricingStrategy) {
|
||||
* this.pricingStrategy = pricingStrategy;
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
* @author Ramnivas Laddad
|
||||
@@ -42,13 +42,13 @@ package org.springframework.beans.factory.aspectj;
|
||||
*/
|
||||
public abstract aspect GenericInterfaceDrivenDependencyInjectionAspect<I> extends AbstractInterfaceDrivenDependencyInjectionAspect {
|
||||
declare parents: I implements ConfigurableObject;
|
||||
|
||||
|
||||
public pointcut inConfigurableBean() : within(I+);
|
||||
|
||||
|
||||
public final void configureBean(Object bean) {
|
||||
configure((I)bean);
|
||||
}
|
||||
|
||||
// Unfortunately, erasure used with generics won't allow to use the same named method
|
||||
|
||||
// Unfortunately, erasure used with generics won't allow to use the same named method
|
||||
protected abstract void configure(I bean);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ public abstract aspect AbstractCacheAspect extends CacheAspectSupport {
|
||||
}
|
||||
};
|
||||
|
||||
return execute(aspectJInvoker, thisJoinPoint.getTarget(), method, thisJoinPoint.getArgs());
|
||||
return execute(aspectJInvoker, thisJoinPoint.getTarget(), method, thisJoinPoint.getArgs());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,9 +23,9 @@ import java.util.List;
|
||||
/**
|
||||
* Abstract aspect to enable mocking of methods picked out by a pointcut.
|
||||
* Sub-aspects must define the mockStaticsTestMethod() pointcut to
|
||||
* indicate call stacks when mocking should be triggered, and the
|
||||
* indicate call stacks when mocking should be triggered, and the
|
||||
* methodToMock() pointcut to pick out a method invocations to mock.
|
||||
*
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
*/
|
||||
@@ -42,7 +42,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
// Represents a list of expected calls to static entity methods
|
||||
// Public to allow inserted code to access: is this normal??
|
||||
public class Expectations {
|
||||
|
||||
|
||||
// Represents an expected call to a static entity method
|
||||
private class Call {
|
||||
private final String signature;
|
||||
@@ -50,21 +50,21 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
|
||||
private Object responseObject; // return value or throwable
|
||||
private CallResponse responseType = CallResponse.nothing;
|
||||
|
||||
|
||||
public Call(String name, Object[] args) {
|
||||
this.signature = name;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
|
||||
public boolean hasResponseSpecified() {
|
||||
return responseType != CallResponse.nothing;
|
||||
}
|
||||
|
||||
|
||||
public void setReturnVal(Object retVal) {
|
||||
this.responseObject = retVal;
|
||||
responseType = CallResponse.return_;
|
||||
}
|
||||
|
||||
|
||||
public void setThrow(Throwable throwable) {
|
||||
this.responseObject = throwable;
|
||||
responseType = CallResponse.throw_;
|
||||
@@ -89,7 +89,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private List<Call> calls = new LinkedList<Call>();
|
||||
|
||||
// Calls already verified
|
||||
@@ -101,7 +101,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
+ " calls, received " + verified);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the call and provide the expected return value
|
||||
* @param lastSig
|
||||
@@ -175,7 +175,7 @@ public abstract aspect AbstractMethodMockingControl percflow(mockStaticsTestMeth
|
||||
return expectations.respond(thisJoinPointStaticPart.toLongString(), thisJoinPoint.getArgs());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void expectReturnInternal(Object retVal) {
|
||||
if (!recording) {
|
||||
throw new IllegalStateException("Not recording: Cannot set return value");
|
||||
|
||||
@@ -18,16 +18,16 @@ package org.springframework.mock.staticmock;
|
||||
|
||||
/**
|
||||
* Annotation-based aspect to use in test build to enable mocking static methods
|
||||
* on JPA-annotated <code>@Entity</code> classes, as used by Roo for finders.
|
||||
* on JPA-annotated {@code @Entity} classes, as used by Roo for finders.
|
||||
*
|
||||
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
|
||||
* that is annotated with the @MockStaticEntityMethods annotation.
|
||||
* <p>Mocking will occur in the call stack of any method in a class (typically a test class)
|
||||
* that is annotated with the @MockStaticEntityMethods annotation.
|
||||
*
|
||||
* <p>Also provides static methods to simplify the programming model for
|
||||
* entering playback mode and setting expected return values.
|
||||
*
|
||||
* <p>Usage:
|
||||
* <ol>
|
||||
* <ol>
|
||||
* <li>Annotate a test class with @MockStaticEntityMethods.
|
||||
* <li>In each test method, AnnotationDrivenStaticEntityMockingControl will begin in recording mode.
|
||||
* Invoke static methods on Entity classes, with each recording-mode invocation
|
||||
@@ -37,20 +37,20 @@ package org.springframework.mock.staticmock;
|
||||
* <li>Call the code you wish to test that uses the static methods. Verification will
|
||||
* occur automatically.
|
||||
* </ol>
|
||||
*
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @see MockStaticEntityMethods
|
||||
*/
|
||||
public aspect AnnotationDrivenStaticEntityMockingControl extends AbstractMethodMockingControl {
|
||||
|
||||
|
||||
/**
|
||||
* Stop recording mock calls and enter playback state
|
||||
*/
|
||||
public static void playback() {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().playbackInternal();
|
||||
}
|
||||
|
||||
|
||||
public static void expectReturn(Object retVal) {
|
||||
AnnotationDrivenStaticEntityMockingControl.aspectOf().expectReturnInternal(retVal);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,19 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.orm.jpa.aspectj;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
@@ -9,14 +25,17 @@ import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.orm.jpa.EntityManagerFactoryUtils;
|
||||
|
||||
public aspect JpaExceptionTranslatorAspect {
|
||||
pointcut entityManagerCall(): call(* EntityManager.*(..)) || call(* EntityManagerFactory.*(..)) || call(* EntityTransaction.*(..)) || call(* Query.*(..));
|
||||
|
||||
after() throwing(RuntimeException re): entityManagerCall() {
|
||||
DataAccessException dex = EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(re);
|
||||
if (dex != null) {
|
||||
throw dex;
|
||||
} else {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
pointcut entityManagerCall():
|
||||
call(* EntityManager.*(..)) || call(* EntityManagerFactory.*(..)) ||
|
||||
call(* EntityTransaction.*(..)) || call(* Query.*(..));
|
||||
|
||||
after() throwing(RuntimeException re): entityManagerCall() {
|
||||
DataAccessException dex = EntityManagerFactoryUtils.convertJpaAccessExceptionIfPossible(re);
|
||||
if (dex != null) {
|
||||
throw dex;
|
||||
}
|
||||
else {
|
||||
throw re;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import org.springframework.core.task.AsyncTaskExecutor;
|
||||
/**
|
||||
* Abstract aspect that routes selected methods asynchronously.
|
||||
*
|
||||
* <p>This aspect needs to be injected with an implementation of
|
||||
* <p>This aspect needs to be injected with an implementation of
|
||||
* {@link Executor} to activate it for a specific thread pool.
|
||||
* Otherwise it will simply delegate all calls synchronously.
|
||||
*
|
||||
|
||||
@@ -16,8 +16,6 @@
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.aspectj.lang.annotation.SuppressAjWarnings;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
@@ -25,7 +23,7 @@ import org.springframework.transaction.interceptor.TransactionAttributeSource;
|
||||
|
||||
/**
|
||||
* Abstract superaspect for AspectJ transaction aspects. Concrete
|
||||
* subaspects will implement the <code>transactionalMethodExecution()</code>
|
||||
* subaspects will implement the {@code transactionalMethodExecution()}
|
||||
* pointcut using a strategy such as Java 5 annotations.
|
||||
*
|
||||
* <p>Suitable for use inside or outside the Spring IoC container.
|
||||
@@ -42,45 +40,42 @@ import org.springframework.transaction.interceptor.TransactionAttributeSource;
|
||||
*
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Juergen Hoeller
|
||||
* @since 2.0
|
||||
*/
|
||||
public abstract aspect AbstractTransactionAspect extends TransactionAspectSupport {
|
||||
|
||||
/**
|
||||
* Construct object using the given transaction metadata retrieval strategy.
|
||||
* Construct the aspect using the given transaction metadata retrieval strategy.
|
||||
* @param tas TransactionAttributeSource implementation, retrieving Spring
|
||||
* transaction metadata for each joinpoint. Write the subclass to pass in null
|
||||
* if it's intended to be configured by Setter Injection.
|
||||
* transaction metadata for each joinpoint. Implement the subclass to pass in
|
||||
* {@code null} if it is intended to be configured through Setter Injection.
|
||||
*/
|
||||
protected AbstractTransactionAspect(TransactionAttributeSource tas) {
|
||||
setTransactionAttributeSource(tas);
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
before(Object txObject) : transactionalMethodExecution(txObject) {
|
||||
Object around(final Object txObject): transactionalMethodExecution(txObject) {
|
||||
MethodSignature methodSignature = (MethodSignature) thisJoinPoint.getSignature();
|
||||
Method method = methodSignature.getMethod();
|
||||
createTransactionIfNecessary(method, txObject.getClass());
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) throwing(Throwable t) : transactionalMethodExecution(txObject) {
|
||||
// Adapt to TransactionAspectSupport's invokeWithinTransaction...
|
||||
try {
|
||||
completeTransactionAfterThrowing(TransactionAspectSupport.currentTransactionInfo(), t);
|
||||
return invokeWithinTransaction(methodSignature.getMethod(), txObject.getClass(), new InvocationCallback() {
|
||||
public Object proceedWithInvocation() throws Throwable {
|
||||
return proceed(txObject);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Throwable t2) {
|
||||
logger.error("Failed to close transaction after throwing in a transactional method", t2);
|
||||
catch (RuntimeException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Error err) {
|
||||
throw err;
|
||||
}
|
||||
catch (Throwable thr) {
|
||||
Rethrower.rethrow(thr);
|
||||
throw new IllegalStateException("Should never get here", thr);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) returning() : transactionalMethodExecution(txObject) {
|
||||
commitTransactionAfterReturning(TransactionAspectSupport.currentTransactionInfo());
|
||||
}
|
||||
|
||||
@SuppressAjWarnings("adviceDidNotMatch")
|
||||
after(Object txObject) : transactionalMethodExecution(txObject) {
|
||||
cleanupTransactionInfo(TransactionAspectSupport.currentTransactionInfo());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,4 +85,22 @@ public abstract aspect AbstractTransactionAspect extends TransactionAspectSuppor
|
||||
*/
|
||||
protected abstract pointcut transactionalMethodExecution(Object txObject);
|
||||
|
||||
|
||||
/**
|
||||
* Ugly but safe workaround: We need to be able to propagate checked exceptions,
|
||||
* despite AspectJ around advice supporting specifically declared exceptions only.
|
||||
*/
|
||||
private static class Rethrower {
|
||||
|
||||
public static void rethrow(final Throwable exception) {
|
||||
class CheckedExceptionRethrower<T extends Throwable> {
|
||||
@SuppressWarnings("unchecked")
|
||||
private void rethrow(Throwable exception) throws T {
|
||||
throw (T) exception;
|
||||
}
|
||||
}
|
||||
new CheckedExceptionRethrower<RuntimeException>().rethrow(exception);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -21,17 +21,17 @@ import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Concrete AspectJ transaction aspect using Spring's @Transactional annotation.
|
||||
*
|
||||
*
|
||||
* <p>When using this aspect, you <i>must</i> annotate the implementation class
|
||||
* (and/or methods within that class), <i>not</i> the interface (if any) that
|
||||
* the class implements. AspectJ follows Java's rule that annotations on
|
||||
* the class implements. AspectJ follows Java's rule that annotations on
|
||||
* interfaces are <i>not</i> inherited.
|
||||
*
|
||||
* <p>An @Transactional annotation on a class specifies the default transaction
|
||||
* semantics for the execution of any <b>public</b> operation in the class.
|
||||
*
|
||||
* <p>An @Transactional annotation on a method within the class overrides the
|
||||
* default transaction semantics given by the class annotation (if present).
|
||||
* default transaction semantics given by the class annotation (if present).
|
||||
* Any method may be annotated (regardless of visibility).
|
||||
* Annotating non-public methods directly is the only way
|
||||
* to get transaction demarcation for the execution of such operations.
|
||||
@@ -49,16 +49,14 @@ public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
|
||||
}
|
||||
|
||||
/**
|
||||
* Matches the execution of any public method in a type with the
|
||||
* Transactional annotation, or any subtype of a type with the
|
||||
* Transactional annotation.
|
||||
* Matches the execution of any public method in a type with the Transactional
|
||||
* annotation, or any subtype of a type with the Transactional annotation.
|
||||
*/
|
||||
private pointcut executionOfAnyPublicMethodInAtTransactionalType() :
|
||||
execution(public * ((@Transactional *)+).*(..)) && within(@Transactional *);
|
||||
|
||||
/**
|
||||
* Matches the execution of any method with the
|
||||
* Transactional annotation.
|
||||
* Matches the execution of any method with the Transactional annotation.
|
||||
*/
|
||||
private pointcut executionOfTransactionalMethod() :
|
||||
execution(@Transactional * *(..));
|
||||
@@ -66,7 +64,7 @@ public aspect AnnotationTransactionAspect extends AbstractTransactionAspect {
|
||||
/**
|
||||
* Definition of pointcut from super aspect - matched join points
|
||||
* will have Spring transaction management applied.
|
||||
*/
|
||||
*/
|
||||
protected pointcut transactionalMethodExecution(Object txObject) :
|
||||
(executionOfAnyPublicMethodInAtTransactionalType()
|
||||
|| executionOfTransactionalMethod() )
|
||||
|
||||
@@ -16,19 +16,18 @@
|
||||
|
||||
package org.springframework.transaction.aspectj;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
import org.springframework.test.AbstractDependencyInjectionSpringContextTests;
|
||||
import org.springframework.tests.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.annotation.AnnotationTransactionAttributeSource;
|
||||
import org.springframework.transaction.interceptor.TransactionAspectSupport;
|
||||
import org.springframework.transaction.interceptor.TransactionAttribute;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* @author Rod Johnson
|
||||
* @author Ramnivas Laddad
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class TransactionAspectTests extends AbstractDependencyInjectionSpringContextTests {
|
||||
|
||||
@@ -123,50 +122,63 @@ public class TransactionAspectTests extends AbstractDependencyInjectionSpringCon
|
||||
|
||||
|
||||
public void testDefaultCommitOnAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return annotationOnlyOnClassWithNoInterface.echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
final Exception ex = new Exception();
|
||||
try {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return annotationOnlyOnClassWithNoInterface.echo(ex);
|
||||
}
|
||||
}, false);
|
||||
fail("Should have thrown Exception");
|
||||
}
|
||||
catch (Exception ex2) {
|
||||
assertSame(ex, ex2);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDefaultRollbackOnAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return annotationOnlyOnClassWithNoInterface.echo(new RuntimeException());
|
||||
}
|
||||
}, true);
|
||||
final RuntimeException ex = new RuntimeException();
|
||||
try {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return annotationOnlyOnClassWithNoInterface.echo(ex);
|
||||
}
|
||||
}, true);
|
||||
fail("Should have thrown RuntimeException");
|
||||
}
|
||||
catch (RuntimeException ex2) {
|
||||
assertSame(ex, ex2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public static class SubclassOfClassWithTransactionalAnnotation extends TransactionalAnnotationOnlyOnClassWithNoInterface {
|
||||
}
|
||||
|
||||
public void testDefaultCommitOnSubclassOfAnnotatedClass() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new SubclassOfClassWithTransactionalAnnotation().echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
public static class SubclassOfClassWithTransactionalMethodAnnotation extends MethodAnnotationOnClassWithNoInterface {
|
||||
final Exception ex = new Exception();
|
||||
try {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new SubclassOfClassWithTransactionalAnnotation().echo(ex);
|
||||
}
|
||||
}, false);
|
||||
fail("Should have thrown Exception");
|
||||
}
|
||||
catch (Exception ex2) {
|
||||
assertSame(ex, ex2);
|
||||
}
|
||||
}
|
||||
|
||||
public void testDefaultCommitOnSubclassOfClassWithTransactionalMethodAnnotated() throws Throwable {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new SubclassOfClassWithTransactionalMethodAnnotation().echo(new Exception());
|
||||
}
|
||||
}, false);
|
||||
}
|
||||
|
||||
public static class ImplementsAnnotatedInterface implements ITransactional {
|
||||
public Object echo(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return t;
|
||||
final Exception ex = new Exception();
|
||||
try {
|
||||
testRollback(new TransactionOperationCallback() {
|
||||
public Object performTransactionalOperation() throws Throwable {
|
||||
return new SubclassOfClassWithTransactionalMethodAnnotation().echo(ex);
|
||||
}
|
||||
}, false);
|
||||
fail("Should have thrown Exception");
|
||||
}
|
||||
catch (Exception ex2) {
|
||||
assertSame(ex, ex2);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -221,18 +233,12 @@ public class TransactionAspectTests extends AbstractDependencyInjectionSpringCon
|
||||
assertEquals(0, txManager.begun);
|
||||
try {
|
||||
toc.performTransactionalOperation();
|
||||
assertEquals(1, txManager.commits);
|
||||
}
|
||||
catch (Throwable caught) {
|
||||
if (caught instanceof AssertionFailedError) {
|
||||
return;
|
||||
}
|
||||
finally {
|
||||
assertEquals(1, txManager.begun);
|
||||
assertEquals(rollback ? 0 : 1, txManager.commits);
|
||||
assertEquals(rollback ? 1 : 0, txManager.rollbacks);
|
||||
}
|
||||
|
||||
if (rollback) {
|
||||
assertEquals(1, txManager.rollbacks);
|
||||
}
|
||||
assertEquals(1, txManager.begun);
|
||||
}
|
||||
|
||||
protected void testNotTransactional(TransactionOperationCallback toc, Throwable expected) throws Throwable {
|
||||
@@ -258,4 +264,23 @@ public class TransactionAspectTests extends AbstractDependencyInjectionSpringCon
|
||||
Object performTransactionalOperation() throws Throwable;
|
||||
}
|
||||
|
||||
|
||||
public static class SubclassOfClassWithTransactionalAnnotation extends TransactionalAnnotationOnlyOnClassWithNoInterface {
|
||||
}
|
||||
|
||||
|
||||
public static class SubclassOfClassWithTransactionalMethodAnnotation extends MethodAnnotationOnClassWithNoInterface {
|
||||
}
|
||||
|
||||
|
||||
public static class ImplementsAnnotatedInterface implements ITransactional {
|
||||
|
||||
public Object echo(Throwable t) throws Throwable {
|
||||
if (t != null) {
|
||||
throw t;
|
||||
}
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -572,29 +572,30 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
|
||||
Class beanClass;
|
||||
if (mbd.getFactoryMethodName() != null) {
|
||||
beanClass = getTypeForFactoryMethod(beanName, mbd, typesToMatch);
|
||||
}
|
||||
else {
|
||||
beanClass = resolveBeanClass(mbd, beanName, typesToMatch);
|
||||
protected Class<?> predictBeanType(String beanName, RootBeanDefinition mbd, Class... typesToMatch) {
|
||||
Class<?> targetType = mbd.getTargetType();
|
||||
if (targetType == null) {
|
||||
targetType = (mbd.getFactoryMethodName() != null ? getTypeForFactoryMethod(beanName, mbd, typesToMatch) :
|
||||
resolveBeanClass(mbd, beanName, typesToMatch));
|
||||
if (ObjectUtils.isEmpty(typesToMatch) || getTempClassLoader() == null) {
|
||||
mbd.setTargetType(targetType);
|
||||
}
|
||||
}
|
||||
// Apply SmartInstantiationAwareBeanPostProcessors to predict the
|
||||
// eventual type after a before-instantiation shortcut.
|
||||
if (beanClass != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
if (targetType != null && !mbd.isSynthetic() && hasInstantiationAwareBeanPostProcessors()) {
|
||||
for (BeanPostProcessor bp : getBeanPostProcessors()) {
|
||||
if (bp instanceof SmartInstantiationAwareBeanPostProcessor) {
|
||||
SmartInstantiationAwareBeanPostProcessor ibp = (SmartInstantiationAwareBeanPostProcessor) bp;
|
||||
Class predictedType = ibp.predictBeanType(beanClass, beanName);
|
||||
if (predictedType != null && (typesToMatch.length > 1 ||
|
||||
!FactoryBean.class.equals(typesToMatch[0]) || FactoryBean.class.isAssignableFrom(predictedType))) {
|
||||
return predictedType;
|
||||
Class predicted = ibp.predictBeanType(targetType, beanName);
|
||||
if (predicted != null && (typesToMatch.length != 1 || !FactoryBean.class.equals(typesToMatch[0]) ||
|
||||
FactoryBean.class.isAssignableFrom(predicted))) {
|
||||
return predicted;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return beanClass;
|
||||
return targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -611,8 +612,8 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
* @return the type for the bean if determinable, or {@code null} else
|
||||
* @see #createBean
|
||||
*/
|
||||
protected Class getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
||||
Class factoryClass;
|
||||
protected Class<?> getTypeForFactoryMethod(String beanName, RootBeanDefinition mbd, Class[] typesToMatch) {
|
||||
Class<?> factoryClass;
|
||||
boolean isStatic = true;
|
||||
|
||||
String factoryBeanName = mbd.getFactoryBeanName();
|
||||
@@ -686,7 +687,7 @@ public abstract class AbstractAutowireCapableBeanFactory extends AbstractBeanFac
|
||||
if (factoryBeanName != null && factoryMethodName != null) {
|
||||
// Try to obtain the FactoryBean's object type without instantiating it at all.
|
||||
BeanDefinition fbDef = getBeanDefinition(factoryBeanName);
|
||||
if (fbDef instanceof AbstractBeanDefinition) {
|
||||
if (fbDef instanceof AbstractBeanDefinition && ((AbstractBeanDefinition) fbDef).hasBeanClass()) {
|
||||
Class<?> fbClass = ((AbstractBeanDefinition) fbDef).getBeanClass();
|
||||
if (ClassUtils.isCglibProxyClass(fbClass)) {
|
||||
// CGLIB subclass methods hide generic parameters. look at the superclass.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -165,7 +165,7 @@ public class PropertiesBeanDefinitionReader extends AbstractBeanDefinitionReader
|
||||
* class can still override this.
|
||||
* <p>Strictly speaking, the rule that a default parent setting does
|
||||
* not apply to a bean definition that carries a class is there for
|
||||
* backwards compatiblity reasons. It still matches the typical use case.
|
||||
* backwards compatibility reasons. It still matches the typical use case.
|
||||
*/
|
||||
public void setDefaultParentBean(String defaultParentBean) {
|
||||
this.defaultParentBean = defaultParentBean;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -61,8 +61,12 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
|
||||
boolean allowCaching = true;
|
||||
|
||||
private volatile Class<?> targetType;
|
||||
|
||||
boolean isFactoryMethodUnique = false;
|
||||
|
||||
final Object constructorArgumentLock = new Object();
|
||||
|
||||
/** Package-visible field for caching the resolved constructor or factory method */
|
||||
Object resolvedConstructorOrFactoryMethod;
|
||||
|
||||
@@ -75,15 +79,13 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
/** Package-visible field for caching partly prepared constructor arguments */
|
||||
Object[] preparedConstructorArguments;
|
||||
|
||||
final Object constructorArgumentLock = new Object();
|
||||
|
||||
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
|
||||
volatile Boolean beforeInstantiationResolved;
|
||||
final Object postProcessingLock = new Object();
|
||||
|
||||
/** Package-visible field that indicates MergedBeanDefinitionPostProcessor having been applied */
|
||||
boolean postProcessed = false;
|
||||
|
||||
final Object postProcessingLock = new Object();
|
||||
/** Package-visible field that indicates a before-instantiation post-processor having kicked in */
|
||||
volatile Boolean beforeInstantiationResolved;
|
||||
|
||||
|
||||
/**
|
||||
@@ -236,6 +238,8 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
if (original instanceof RootBeanDefinition) {
|
||||
RootBeanDefinition originalRbd = (RootBeanDefinition) original;
|
||||
this.decoratedDefinition = originalRbd.decoratedDefinition;
|
||||
this.allowCaching = originalRbd.allowCaching;
|
||||
this.targetType = originalRbd.targetType;
|
||||
this.isFactoryMethodUnique = originalRbd.isFactoryMethodUnique;
|
||||
}
|
||||
}
|
||||
@@ -251,6 +255,21 @@ public class RootBeanDefinition extends AbstractBeanDefinition {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the target type of this bean definition, if known in advance.
|
||||
*/
|
||||
public void setTargetType(Class<?> targetType) {
|
||||
this.targetType = targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the target type of this bean definition, if known
|
||||
* (either specified in advance or resolved on first instantiation).
|
||||
*/
|
||||
public Class<?> getTargetType() {
|
||||
return this.targetType;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify a factory method name that refers to a non-overloaded method.
|
||||
*/
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -30,14 +30,13 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
/**
|
||||
* Convenient base class for configurers that can perform Dependency Injection
|
||||
* Convenient base class for bean configurers that can perform Dependency Injection
|
||||
* on objects (however they may be created). Typically subclassed by AspectJ aspects.
|
||||
*
|
||||
* <p>Subclasses may also need a custom metadata resolution strategy, in the
|
||||
* {@link BeanWiringInfoResolver} interface. The default implementation looks
|
||||
* for a bean with the same name as the fully-qualified class name. (This is
|
||||
* the default name of the bean in a Spring XML file if the '{@code id}'
|
||||
* attribute is not used.)
|
||||
* {@link BeanWiringInfoResolver} interface. The default implementation looks for
|
||||
* a bean with the same name as the fully-qualified class name. (This is the default
|
||||
* name of the bean in a Spring XML file if the '{@code id}' attribute is not used.)
|
||||
|
||||
* @author Rob Harrop
|
||||
* @author Rod Johnson
|
||||
@@ -113,8 +112,7 @@ public class BeanConfigurerSupport implements BeanFactoryAware, InitializingBean
|
||||
/**
|
||||
* Configure the bean instance.
|
||||
* <p>Subclasses can override this to provide custom configuration logic.
|
||||
* Typically called by an aspect, for all bean instances matched by a
|
||||
* pointcut.
|
||||
* Typically called by an aspect, for all bean instances matched by a pointcut.
|
||||
* @param beanInstance the bean instance to configure (must <b>not</b> be {@code null})
|
||||
*/
|
||||
public void configureBean(Object beanInstance) {
|
||||
|
||||
@@ -591,7 +591,6 @@ public class DefaultListableBeanFactoryTests {
|
||||
fail("Should throw exception on invalid property");
|
||||
}
|
||||
catch (BeanCreationException ex) {
|
||||
ex.printStackTrace();
|
||||
assertTrue(ex.getCause() instanceof NotWritablePropertyException);
|
||||
NotWritablePropertyException cause = (NotWritablePropertyException) ex.getCause();
|
||||
// expected
|
||||
|
||||
@@ -29,7 +29,6 @@ import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
@@ -78,7 +77,6 @@ public final class CustomProblemReporterTests {
|
||||
|
||||
@Override
|
||||
public void error(Problem problem) {
|
||||
System.out.println(problem);
|
||||
this.errors.add(problem);
|
||||
}
|
||||
|
||||
@@ -88,7 +86,6 @@ public final class CustomProblemReporterTests {
|
||||
|
||||
@Override
|
||||
public void warning(Problem problem) {
|
||||
System.out.println(problem);
|
||||
this.warnings.add(problem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,12 +16,6 @@
|
||||
|
||||
package org.springframework.beans.factory.support.security;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.net.URL;
|
||||
import java.security.AccessControlContext;
|
||||
@@ -39,8 +33,8 @@ import javax.security.auth.AuthPermission;
|
||||
import javax.security.auth.Subject;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
@@ -60,6 +54,8 @@ import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.core.io.DefaultResourceLoader;
|
||||
import org.springframework.core.io.Resource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Security test case. Checks whether the container uses its privileges for its
|
||||
* internal work but does not leak them when touching/calling user code.
|
||||
@@ -456,9 +452,6 @@ public class CallbacksSecurityTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
@Ignore("passes under Eclipse, but fails under Gradle with https://gist.github.com/1664133")
|
||||
// TODO [SPR-10074] passes under Eclipse, but fails under Gradle with
|
||||
// https://gist.github.com/1664133
|
||||
public void testContainerPrivileges() throws Exception {
|
||||
AccessControlContext acc = provider.getAccessControlContext();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.beans.factory.support.security.support;
|
||||
|
||||
/**
|
||||
@@ -25,6 +26,5 @@ public class ConstructorBean {
|
||||
}
|
||||
|
||||
public ConstructorBean(Object obj) {
|
||||
System.out.println("Received object " + obj);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,21 +11,13 @@
|
||||
</layout>
|
||||
</appender>
|
||||
|
||||
<logger name="org.springframework.beans">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.binding">
|
||||
<level value="debug" />
|
||||
</logger>
|
||||
|
||||
<logger name="org.springframework.core.GenericTypeResolver">
|
||||
<logger name="org.springframework.beans.factory.config.DeprecatedBeanWarnerTests$MyDeprecatedBeanWarner">
|
||||
<level value="warn" />
|
||||
</logger>
|
||||
|
||||
<!-- Root Logger -->
|
||||
<root>
|
||||
<priority value="warn" />
|
||||
<priority value="error" />
|
||||
<appender-ref ref="console" />
|
||||
</root>
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -40,9 +40,9 @@ import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} that creates a named EHCache {@link net.sf.ehcache.Cache} instance
|
||||
* {@link FactoryBean} that creates a named EhCache {@link net.sf.ehcache.Cache} instance
|
||||
* (or a decorator that implements the {@link net.sf.ehcache.Ehcache} interface),
|
||||
* representing a cache region within an EHCache {@link net.sf.ehcache.CacheManager}.
|
||||
* representing a cache region within an EhCache {@link net.sf.ehcache.CacheManager}.
|
||||
*
|
||||
* <p>If the specified named cache is not configured in the cache configuration descriptor,
|
||||
* this FactoryBean will construct an instance of a Cache with the provided name and the
|
||||
@@ -52,7 +52,8 @@ import org.springframework.util.Assert;
|
||||
* <p>Note: If the named Cache instance is found, the properties will be ignored and the
|
||||
* Cache instance will be retrieved from the CacheManager.
|
||||
*
|
||||
* <p>Note: As of Spring 3.0, Spring's EHCache support requires EHCache 1.3 or higher.
|
||||
* <p>Note: As of Spring 3.0, Spring's EhCache support requires EhCache 1.3 or higher.
|
||||
* As of Spring 3.2, we recommend using EhCache 2.1 or higher.
|
||||
|
||||
* @author Dmitriy Kopylenko
|
||||
* @author Juergen Hoeller
|
||||
@@ -117,7 +118,7 @@ public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
|
||||
* properly handle the shutdown of the CacheManager: Set up a separate
|
||||
* EhCacheManagerFactoryBean and pass a reference to this bean property.
|
||||
* <p>A separate EhCacheManagerFactoryBean is also necessary for loading
|
||||
* EHCache configuration from a non-default config location.
|
||||
* EhCache configuration from a non-default config location.
|
||||
* @see EhCacheManagerFactoryBean
|
||||
* @see net.sf.ehcache.CacheManager#getInstance
|
||||
*/
|
||||
@@ -152,7 +153,7 @@ public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
|
||||
/**
|
||||
* Set the memory style eviction policy for this cache.
|
||||
* <p>Supported values are "LRU", "LFU" and "FIFO", according to the
|
||||
* constants defined in EHCache's MemoryStoreEvictionPolicy class.
|
||||
* constants defined in EhCache's MemoryStoreEvictionPolicy class.
|
||||
* Default is "LRU".
|
||||
*/
|
||||
public void setMemoryStoreEvictionPolicy(MemoryStoreEvictionPolicy memoryStoreEvictionPolicy) {
|
||||
@@ -239,9 +240,9 @@ public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an EHCache {@link net.sf.ehcache.constructs.blocking.CacheEntryFactory}
|
||||
* Set an EhCache {@link net.sf.ehcache.constructs.blocking.CacheEntryFactory}
|
||||
* to use for a self-populating cache. If such a factory is specified,
|
||||
* the cache will be decorated with EHCache's
|
||||
* the cache will be decorated with EhCache's
|
||||
* {@link net.sf.ehcache.constructs.blocking.SelfPopulatingCache}.
|
||||
* <p>The specified factory can be of type
|
||||
* {@link net.sf.ehcache.constructs.blocking.UpdatingCacheEntryFactory},
|
||||
@@ -257,7 +258,7 @@ public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an EHCache {@link net.sf.ehcache.bootstrap.BootstrapCacheLoader}
|
||||
* Set an EhCache {@link net.sf.ehcache.bootstrap.BootstrapCacheLoader}
|
||||
* for this cache, if any.
|
||||
*/
|
||||
public void setBootstrapCacheLoader(BootstrapCacheLoader bootstrapCacheLoader) {
|
||||
@@ -265,7 +266,7 @@ public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify EHCache {@link net.sf.ehcache.event.CacheEventListener cache event listeners}
|
||||
* Specify EhCache {@link net.sf.ehcache.event.CacheEventListener cache event listeners}
|
||||
* to registered with this cache.
|
||||
*/
|
||||
public void setCacheEventListeners(Set<CacheEventListener> cacheEventListeners) {
|
||||
@@ -305,7 +306,7 @@ public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
|
||||
// If no CacheManager given, fetch the default.
|
||||
if (this.cacheManager == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Using default EHCache CacheManager for cache region '" + this.cacheName + "'");
|
||||
logger.debug("Using default EhCache CacheManager for cache region '" + this.cacheName + "'");
|
||||
}
|
||||
this.cacheManager = CacheManager.getInstance();
|
||||
}
|
||||
@@ -320,13 +321,13 @@ public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
|
||||
Ehcache rawCache;
|
||||
if (this.cacheManager.cacheExists(this.cacheName)) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Using existing EHCache cache region '" + this.cacheName + "'");
|
||||
logger.debug("Using existing EhCache cache region '" + this.cacheName + "'");
|
||||
}
|
||||
rawCache = this.cacheManager.getEhcache(this.cacheName);
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Creating new EHCache cache region '" + this.cacheName + "'");
|
||||
logger.debug("Creating new EhCache cache region '" + this.cacheName + "'");
|
||||
}
|
||||
rawCache = createCache();
|
||||
this.cacheManager.addCache(rawCache);
|
||||
@@ -359,7 +360,7 @@ public class EhCacheFactoryBean implements FactoryBean<Ehcache>, BeanNameAware,
|
||||
* Create a raw Cache object based on the configuration of this FactoryBean.
|
||||
*/
|
||||
protected Cache createCache() {
|
||||
// Only call EHCache 1.6 constructor if actually necessary (for compatibility with EHCache 1.3+)
|
||||
// Only call EhCache 1.6 constructor if actually necessary (for compatibility with EhCache 1.3+)
|
||||
return (!this.clearOnFlush) ?
|
||||
new Cache(this.cacheName, this.maxElementsInMemory, this.memoryStoreEvictionPolicy,
|
||||
this.overflowToDisk, null, this.eternal, this.timeToLive, this.timeToIdle,
|
||||
|
||||
@@ -35,19 +35,20 @@ import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
/**
|
||||
* {@link FactoryBean} that exposes an EHCache {@link net.sf.ehcache.CacheManager}
|
||||
* {@link FactoryBean} that exposes an EhCache {@link net.sf.ehcache.CacheManager}
|
||||
* instance (independent or shared), configured from a specified config location.
|
||||
*
|
||||
* <p>If no config location is specified, a CacheManager will be configured from
|
||||
* "ehcache.xml" in the root of the class path (that is, default EHCache initialization
|
||||
* - as defined in the EHCache docs - will apply).
|
||||
* "ehcache.xml" in the root of the class path (that is, default EhCache initialization
|
||||
* - as defined in the EhCache docs - will apply).
|
||||
*
|
||||
* <p>Setting up a separate EhCacheManagerFactoryBean is also advisable when using
|
||||
* EhCacheFactoryBean, as it provides a (by default) independent CacheManager instance
|
||||
* and cares for proper shutdown of the CacheManager. EhCacheManagerFactoryBean is
|
||||
* also necessary for loading EHCache configuration from a non-default config location.
|
||||
* also necessary for loading EhCache configuration from a non-default config location.
|
||||
*
|
||||
* <p>Note: As of Spring 3.0, Spring's EHCache support requires EHCache 1.3 or higher.
|
||||
* <p>Note: As of Spring 3.0, Spring's EhCache support requires EhCache 1.3 or higher.
|
||||
* As of Spring 3.2, we recommend using EhCache 2.1 or higher.
|
||||
*
|
||||
* @author Dmitriy Kopylenko
|
||||
* @author Juergen Hoeller
|
||||
@@ -59,7 +60,7 @@ import org.springframework.util.ReflectionUtils;
|
||||
*/
|
||||
public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, InitializingBean, DisposableBean {
|
||||
|
||||
// Check whether EHCache 2.1+ CacheManager.create(Configuration) method is available...
|
||||
// Check whether EhCache 2.1+ CacheManager.create(Configuration) method is available...
|
||||
private static final Method createWithConfiguration =
|
||||
ClassUtils.getMethodIfAvailable(CacheManager.class, "create", Configuration.class);
|
||||
|
||||
@@ -75,9 +76,9 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
|
||||
|
||||
|
||||
/**
|
||||
* Set the location of the EHCache config file. A typical value is "/WEB-INF/ehcache.xml".
|
||||
* Set the location of the EhCache config file. A typical value is "/WEB-INF/ehcache.xml".
|
||||
* <p>Default is "ehcache.xml" in the root of the class path, or if not found,
|
||||
* "ehcache-failsafe.xml" in the EHCache jar (default EHCache initialization).
|
||||
* "ehcache-failsafe.xml" in the EhCache jar (default EhCache initialization).
|
||||
* @see net.sf.ehcache.CacheManager#create(java.io.InputStream)
|
||||
* @see net.sf.ehcache.CacheManager#CacheManager(java.io.InputStream)
|
||||
*/
|
||||
@@ -86,7 +87,7 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
|
||||
}
|
||||
|
||||
/**
|
||||
* Set whether the EHCache CacheManager should be shared (as a singleton at the VM level)
|
||||
* Set whether the EhCache CacheManager should be shared (as a singleton at the VM level)
|
||||
* or independent (typically local within the application). Default is "false", creating
|
||||
* an independent instance.
|
||||
* @see net.sf.ehcache.CacheManager#create()
|
||||
@@ -97,7 +98,7 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the name of the EHCache CacheManager (if a specific name is desired).
|
||||
* Set the name of the EhCache CacheManager (if a specific name is desired).
|
||||
* @see net.sf.ehcache.CacheManager#setName(String)
|
||||
*/
|
||||
public void setCacheManagerName(String cacheManagerName) {
|
||||
@@ -106,14 +107,14 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
|
||||
|
||||
|
||||
public void afterPropertiesSet() throws IOException, CacheException {
|
||||
logger.info("Initializing EHCache CacheManager");
|
||||
logger.info("Initializing EhCache CacheManager");
|
||||
InputStream is = (this.configLocation != null ? this.configLocation.getInputStream() : null);
|
||||
try {
|
||||
// A bit convoluted for EHCache 1.x/2.0 compatibility.
|
||||
// To be much simpler once we require EHCache 2.1+
|
||||
// A bit convoluted for EhCache 1.x/2.0 compatibility.
|
||||
// To be much simpler once we require EhCache 2.1+
|
||||
if (this.cacheManagerName != null) {
|
||||
if (this.shared && createWithConfiguration == null) {
|
||||
// No CacheManager.create(Configuration) method available before EHCache 2.1;
|
||||
// No CacheManager.create(Configuration) method available before EhCache 2.1;
|
||||
// can only set CacheManager name after creation.
|
||||
this.cacheManager = (is != null ? CacheManager.create(is) : CacheManager.create());
|
||||
this.cacheManager.setName(this.cacheManagerName);
|
||||
@@ -160,7 +161,7 @@ public class EhCacheManagerFactoryBean implements FactoryBean<CacheManager>, Ini
|
||||
|
||||
|
||||
public void destroy() {
|
||||
logger.info("Shutting down EHCache CacheManager");
|
||||
logger.info("Shutting down EhCache CacheManager");
|
||||
this.cacheManager.shutdown();
|
||||
}
|
||||
|
||||
|
||||
@@ -133,7 +133,6 @@ public class EhCacheSupportTests extends TestCase {
|
||||
cacheFb.setBeanName("undefinedCache2");
|
||||
cacheFb.setMaxElementsInMemory(5);
|
||||
cacheFb.setOverflowToDisk(false);
|
||||
cacheFb.setEternal(true);
|
||||
cacheFb.setTimeToLive(8);
|
||||
cacheFb.setTimeToIdle(7);
|
||||
cacheFb.setDiskPersistent(true);
|
||||
@@ -145,7 +144,6 @@ public class EhCacheSupportTests extends TestCase {
|
||||
assertEquals("undefinedCache2", cache.getName());
|
||||
assertTrue("overridden maxElements is correct", config.getMaxElementsInMemory() == 5);
|
||||
assertFalse("overridden overflowToDisk is correct", config.isOverflowToDisk());
|
||||
assertTrue("overridden eternal is correct", config.isEternal());
|
||||
assertTrue("default timeToLive is correct", config.getTimeToLiveSeconds() == 8);
|
||||
assertTrue("default timeToIdle is correct", config.getTimeToIdleSeconds() == 7);
|
||||
assertTrue("overridden diskPersistent is correct", config.isDiskPersistent());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,7 @@
|
||||
|
||||
package org.springframework.cache.annotation;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* Group annotation for multiple cache annotations (of different or the same type).
|
||||
@@ -30,7 +25,7 @@ import java.lang.annotation.Target;
|
||||
* @author Chris Beams
|
||||
* @since 3.1
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.TYPE })
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Inherited
|
||||
@Documented
|
||||
@@ -41,4 +36,5 @@ public @interface Caching {
|
||||
CachePut[] put() default {};
|
||||
|
||||
CacheEvict[] evict() default {};
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -177,7 +177,7 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
* @see org.springframework.beans.factory.annotation.Autowired
|
||||
* @see org.springframework.beans.factory.annotation.Value
|
||||
*/
|
||||
@Target({ ElementType.METHOD, ElementType.ANNOTATION_TYPE })
|
||||
@Target({ElementType.METHOD, ElementType.ANNOTATION_TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
public @interface Bean {
|
||||
@@ -190,7 +190,7 @@ public @interface Bean {
|
||||
String[] name() default {};
|
||||
|
||||
/**
|
||||
* Are dependencies to be injected via autowiring?
|
||||
* Are dependencies to be injected via convention-based autowiring by name or type?
|
||||
*/
|
||||
Autowire autowire() default Autowire.NO;
|
||||
|
||||
|
||||
@@ -17,17 +17,11 @@
|
||||
package org.springframework.context.annotation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.CallbackFilter;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.cglib.proxy.NoOp;
|
||||
|
||||
import org.springframework.aop.scope.ScopedProxyFactoryBean;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
@@ -35,6 +29,12 @@ import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
|
||||
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
|
||||
import org.springframework.beans.factory.support.SimpleInstantiationStrategy;
|
||||
import org.springframework.cglib.proxy.Callback;
|
||||
import org.springframework.cglib.proxy.CallbackFilter;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.cglib.proxy.MethodProxy;
|
||||
import org.springframework.cglib.proxy.NoOp;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -52,8 +52,8 @@ class ConfigurationClassEnhancer {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(ConfigurationClassEnhancer.class);
|
||||
|
||||
private static final Class<?>[] CALLBACK_TYPES = { BeanMethodInterceptor.class,
|
||||
DisposableBeanMethodInterceptor.class, NoOp.class };
|
||||
private static final Class<?>[] CALLBACK_TYPES = {BeanMethodInterceptor.class,
|
||||
DisposableBeanMethodInterceptor.class, NoOp.class};
|
||||
|
||||
private static final CallbackFilter CALLBACK_FILTER = new CallbackFilter() {
|
||||
public int accept(Method candidateMethod) {
|
||||
@@ -80,10 +80,8 @@ class ConfigurationClassEnhancer {
|
||||
public ConfigurationClassEnhancer(ConfigurableBeanFactory beanFactory) {
|
||||
Assert.notNull(beanFactory, "BeanFactory must not be null");
|
||||
// Callback instances must be ordered in the same way as CALLBACK_TYPES and CALLBACK_FILTER
|
||||
this.callbackInstances = new Callback[] {
|
||||
new BeanMethodInterceptor(beanFactory),
|
||||
DISPOSABLE_BEAN_METHOD_INTERCEPTOR,
|
||||
NoOp.INSTANCE };
|
||||
this.callbackInstances = new Callback[]
|
||||
{new BeanMethodInterceptor(beanFactory), DISPOSABLE_BEAN_METHOD_INTERCEPTOR, NoOp.INSTANCE};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -169,9 +167,8 @@ class ConfigurationClassEnhancer {
|
||||
}
|
||||
|
||||
public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
|
||||
return beanFactory.getBean(beanName);
|
||||
return this.beanFactory.getBean(this.beanName);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -209,19 +206,16 @@ class ConfigurationClassEnhancer {
|
||||
*/
|
||||
private static class BeanMethodInterceptor implements MethodInterceptor {
|
||||
|
||||
private static final Class<?>[] CALLBACK_TYPES = {
|
||||
GetObjectMethodInterceptor.class, NoOp.class };
|
||||
private static final Class<?>[] CALLBACK_TYPES = {GetObjectMethodInterceptor.class, NoOp.class};
|
||||
|
||||
private static final CallbackFilter CALLBACK_FITLER = new CallbackFilter() {
|
||||
private static final CallbackFilter CALLBACK_FILTER = new CallbackFilter() {
|
||||
public int accept(Method method) {
|
||||
return method.getName().equals("getObject") ? 0 : 1;
|
||||
return (method.getName().equals("getObject") ? 0 : 1);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private final ConfigurableBeanFactory beanFactory;
|
||||
|
||||
|
||||
public BeanMethodInterceptor(ConfigurableBeanFactory beanFactory) {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
@@ -229,7 +223,6 @@ class ConfigurationClassEnhancer {
|
||||
/**
|
||||
* Enhance a {@link Bean @Bean} method to check the supplied BeanFactory for the
|
||||
* existence of this bean object.
|
||||
*
|
||||
* @throws Throwable as a catch-all for any exception that may be thrown when
|
||||
* invoking the super implementation of the proxied method i.e., the actual
|
||||
* {@code @Bean} method.
|
||||
@@ -255,8 +248,8 @@ class ConfigurationClassEnhancer {
|
||||
// proxy that intercepts calls to getObject() and returns any cached bean instance.
|
||||
// this ensures that the semantics of calling a FactoryBean from within @Bean methods
|
||||
// is the same as that of referring to a FactoryBean within XML. See SPR-6602.
|
||||
if (factoryContainsBean('&'+beanName) && factoryContainsBean(beanName)) {
|
||||
Object factoryBean = this.beanFactory.getBean('&'+beanName);
|
||||
if (factoryContainsBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName) && factoryContainsBean(beanName)) {
|
||||
Object factoryBean = this.beanFactory.getBean(BeanFactory.FACTORY_BEAN_PREFIX + beanName);
|
||||
if (factoryBean instanceof ScopedProxyFactoryBean) {
|
||||
// pass through - scoped proxy factory beans are a special case and should not
|
||||
// be further proxied
|
||||
@@ -267,9 +260,7 @@ class ConfigurationClassEnhancer {
|
||||
}
|
||||
}
|
||||
|
||||
boolean factoryIsCaller = beanMethod.equals(SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod());
|
||||
boolean factoryAlreadyContainsSingleton = this.beanFactory.containsSingleton(beanName);
|
||||
if (factoryIsCaller && !factoryAlreadyContainsSingleton) {
|
||||
if (isCurrentlyInvokedFactoryMethod(beanMethod) && !this.beanFactory.containsSingleton(beanName)) {
|
||||
// the factory is calling the bean method in order to instantiate and register the bean
|
||||
// (i.e. via a getBean() call) -> invoke the super implementation of the method to actually
|
||||
// create the bean instance.
|
||||
@@ -306,7 +297,7 @@ class ConfigurationClassEnhancer {
|
||||
}
|
||||
|
||||
/**
|
||||
* Check the beanFactory to see whether the bean named <var>beanName</var> already
|
||||
* Check the BeanFactory to see whether the bean named <var>beanName</var> already
|
||||
* exists. Accounts for the fact that the requested bean may be "in creation", i.e.:
|
||||
* we're in the middle of servicing the initial request for this bean. From an enhanced
|
||||
* factory method's perspective, this means that the bean does not actually yet exist,
|
||||
@@ -319,9 +310,19 @@ class ConfigurationClassEnhancer {
|
||||
* @return whether <var>beanName</var> already exists in the factory
|
||||
*/
|
||||
private boolean factoryContainsBean(String beanName) {
|
||||
boolean containsBean = this.beanFactory.containsBean(beanName);
|
||||
boolean currentlyInCreation = this.beanFactory.isCurrentlyInCreation(beanName);
|
||||
return (containsBean && !currentlyInCreation);
|
||||
return (this.beanFactory.containsBean(beanName) && !this.beanFactory.isCurrentlyInCreation(beanName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether the given method corresponds to the container's currently invoked
|
||||
* factory method. Compares method name and parameter types only in order to work
|
||||
* around a potential problem with covariant return types (currently only known
|
||||
* to happen on Groovy classes).
|
||||
*/
|
||||
private boolean isCurrentlyInvokedFactoryMethod(Method method) {
|
||||
Method currentlyInvoked = SimpleInstantiationStrategy.getCurrentlyInvokedFactoryMethod();
|
||||
return (currentlyInvoked != null && method.getName().equals(currentlyInvoked.getName()) &&
|
||||
Arrays.equals(method.getParameterTypes(), currentlyInvoked.getParameterTypes()));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -335,13 +336,12 @@ class ConfigurationClassEnhancer {
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(fbClass);
|
||||
enhancer.setUseFactory(false);
|
||||
enhancer.setCallbackFilter(CALLBACK_FITLER);
|
||||
enhancer.setCallbackFilter(CALLBACK_FILTER);
|
||||
// Callback instances must be ordered in the same way as CALLBACK_TYPES and CALLBACK_FILTER
|
||||
Callback[] callbackInstances = new Callback[] {
|
||||
new GetObjectMethodInterceptor(this.beanFactory, beanName),
|
||||
NoOp.INSTANCE
|
||||
};
|
||||
|
||||
enhancer.setCallbackTypes(CALLBACK_TYPES);
|
||||
Class<?> fbSubclass = enhancer.createClass();
|
||||
Enhancer.registerCallbacks(fbSubclass, callbackInstances);
|
||||
|
||||
@@ -40,20 +40,24 @@ import org.springframework.util.Assert;
|
||||
public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
|
||||
|
||||
private DateFormatter dateFormatter = new DateFormatter();
|
||||
private DateFormatter dateFormatter;
|
||||
|
||||
|
||||
public void registerFormatters(FormatterRegistry registry) {
|
||||
addDateConverters(registry);
|
||||
registry.addFormatter(dateFormatter);
|
||||
registry.addFormatterForFieldType(Calendar.class, dateFormatter);
|
||||
registry.addFormatterForFieldAnnotation(new DateTimeFormatAnnotationFormatterFactory());
|
||||
|
||||
// In order to retain back compatibility we only register Date/Calendar
|
||||
// types when a user defined formatter is specified (see SPR-10105)
|
||||
if(this.dateFormatter != null) {
|
||||
registry.addFormatter(this.dateFormatter);
|
||||
registry.addFormatterForFieldType(Calendar.class, this.dateFormatter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the date formatter to register. If not specified the default {@link DateFormatter}
|
||||
* will be used. This method can be used if additional formatter configuration is
|
||||
* required.
|
||||
* Set the date formatter to register. If not specified no formatter is registered.
|
||||
* This method can be used if global formatter configuration is required.
|
||||
* @param dateFormatter the date formatter
|
||||
*/
|
||||
public void setFormatter(DateFormatter dateFormatter) {
|
||||
@@ -117,7 +121,7 @@ public class DateFormatterRegistrar implements FormatterRegistrar {
|
||||
private DateToCalendarConverter dateToCalendarConverter = new DateToCalendarConverter();
|
||||
|
||||
public Calendar convert(Long source) {
|
||||
return dateToCalendarConverter.convert(new Date(source));
|
||||
return this.dateToCalendarConverter.convert(new Date(source));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -75,7 +75,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* Default is {@link DateTimeFormat#shortDate()}.
|
||||
*/
|
||||
public void setDateStyle(String dateStyle) {
|
||||
factories.get(Type.DATE).setStyle(dateStyle+"-");
|
||||
this.factories.get(Type.DATE).setStyle(dateStyle+"-");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,7 +83,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* Default is {@link DateTimeFormat#shortTime()}.
|
||||
*/
|
||||
public void setTimeStyle(String timeStyle) {
|
||||
factories.get(Type.TIME).setStyle("-"+timeStyle);
|
||||
this.factories.get(Type.TIME).setStyle("-"+timeStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -92,7 +92,7 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* Default is {@link DateTimeFormat#shortDateTime()}.
|
||||
*/
|
||||
public void setDateTimeStyle(String dateTimeStyle) {
|
||||
factories.get(Type.DATE_TIME).setStyle(dateTimeStyle);
|
||||
this.factories.get(Type.DATE_TIME).setStyle(dateTimeStyle);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -101,9 +101,9 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
* If set to true, the dateStyle, timeStyle, and dateTimeStyle properties are ignored.
|
||||
*/
|
||||
public void setUseIsoFormat(boolean useIsoFormat) {
|
||||
factories.get(Type.DATE).setIso(useIsoFormat ? ISO.DATE : null);
|
||||
factories.get(Type.TIME).setIso(useIsoFormat ? ISO.TIME : null);
|
||||
factories.get(Type.DATE_TIME).setIso(useIsoFormat ? ISO.DATE_TIME : null);
|
||||
this.factories.get(Type.DATE).setIso(useIsoFormat ? ISO.DATE : null);
|
||||
this.factories.get(Type.TIME).setIso(useIsoFormat ? ISO.TIME : null);
|
||||
this.factories.get(Type.DATE_TIME).setIso(useIsoFormat ? ISO.DATE_TIME : null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,19 +174,28 @@ public class JodaTimeFormatterRegistrar implements FormatterRegistrar {
|
||||
addFormatterForFields(registry,
|
||||
new ReadableInstantPrinter(dateTimeFormatter),
|
||||
new DateTimeParser(dateTimeFormatter),
|
||||
ReadableInstant.class, Date.class, Calendar.class);
|
||||
ReadableInstant.class);
|
||||
|
||||
// In order to retain back compatibility we only register Date/Calendar
|
||||
// types when a user defined formatter is specified (see SPR-10105)
|
||||
if(this.formatters.containsKey(Type.DATE_TIME)) {
|
||||
addFormatterForFields(registry,
|
||||
new ReadableInstantPrinter(dateTimeFormatter),
|
||||
new DateTimeParser(dateTimeFormatter),
|
||||
Date.class, Calendar.class);
|
||||
}
|
||||
|
||||
registry.addFormatterForFieldAnnotation(
|
||||
new JodaDateTimeFormatAnnotationFormatterFactory());
|
||||
}
|
||||
|
||||
private DateTimeFormatter getFormatter(Type type) {
|
||||
DateTimeFormatter formatter = formatters.get(type);
|
||||
DateTimeFormatter formatter = this.formatters.get(type);
|
||||
if(formatter != null) {
|
||||
return formatter;
|
||||
}
|
||||
DateTimeFormatter fallbackFormatter = getFallbackFormatter(type);
|
||||
return factories.get(type).createDateTimeFormatter(fallbackFormatter );
|
||||
return this.factories.get(type).createDateTimeFormatter(fallbackFormatter );
|
||||
}
|
||||
|
||||
private DateTimeFormatter getFallbackFormatter(Type type) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -39,7 +39,7 @@ public class AnnotationAsyncExecutionInterceptor extends AsyncExecutionIntercept
|
||||
/**
|
||||
* Create a new {@code AnnotationAsyncExecutionInterceptor} with the given executor.
|
||||
* @param defaultExecutor the executor to be used by default if no more specific
|
||||
* executor has been qualified at the method level using {@link Async#value()}.
|
||||
* executor has been qualified at the method level using {@link Async#value()}
|
||||
*/
|
||||
public AnnotationAsyncExecutionInterceptor(Executor defaultExecutor) {
|
||||
super(defaultExecutor);
|
||||
@@ -64,7 +64,7 @@ public class AnnotationAsyncExecutionInterceptor extends AsyncExecutionIntercept
|
||||
if (async == null) {
|
||||
async = AnnotationUtils.findAnnotation(method.getDeclaringClass(), Async.class);
|
||||
}
|
||||
return async == null ? null : async.value();
|
||||
return (async != null ? async.value() : null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,7 +28,6 @@ import org.springframework.aop.Pointcut;
|
||||
import org.springframework.aop.support.AbstractPointcutAdvisor;
|
||||
import org.springframework.aop.support.ComposablePointcut;
|
||||
import org.springframework.aop.support.annotation.AnnotationMatchingPointcut;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.core.task.SimpleAsyncTaskExecutor;
|
||||
@@ -58,8 +57,6 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
|
||||
|
||||
private Pointcut pointcut;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code AsyncAnnotationAdvisor} for bean-style configuration.
|
||||
@@ -84,30 +81,15 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
|
||||
// If EJB 3.1 API not present, simply ignore.
|
||||
}
|
||||
this.advice = buildAdvice(executor);
|
||||
this.setTaskExecutor(executor);
|
||||
this.pointcut = buildPointcut(asyncAnnotationTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code BeanFactory} to be used when looking up executors by qualifier.
|
||||
*/
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
delegateBeanFactory(beanFactory);
|
||||
}
|
||||
|
||||
public void delegateBeanFactory(BeanFactory beanFactory) {
|
||||
if (this.advice instanceof AnnotationAsyncExecutionInterceptor) {
|
||||
((AnnotationAsyncExecutionInterceptor)this.advice).setBeanFactory(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the task executor to use for asynchronous methods.
|
||||
* Specify the default task executor to use for asynchronous methods.
|
||||
*/
|
||||
public void setTaskExecutor(Executor executor) {
|
||||
this.advice = buildAdvice(executor);
|
||||
delegateBeanFactory(this.beanFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,6 +108,15 @@ public class AsyncAnnotationAdvisor extends AbstractPointcutAdvisor implements B
|
||||
this.pointcut = buildPointcut(asyncAnnotationTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the {@code BeanFactory} to be used when looking up executors by qualifier.
|
||||
*/
|
||||
public void setBeanFactory(BeanFactory beanFactory) {
|
||||
if (this.advice instanceof BeanFactoryAware) {
|
||||
((BeanFactoryAware) this.advice).setBeanFactory(beanFactory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Advice getAdvice() {
|
||||
return this.advice;
|
||||
|
||||
@@ -71,7 +71,19 @@ public class CronSequenceGenerator {
|
||||
|
||||
|
||||
/**
|
||||
* Construct a {@link CronSequenceGenerator} from the pattern provided.
|
||||
* Construct a {@link CronSequenceGenerator} from the pattern provided,
|
||||
* using the default {@link TimeZone}.
|
||||
* @param expression a space-separated list of time fields
|
||||
* @throws IllegalArgumentException if the pattern cannot be parsed
|
||||
* @see java.util.TimeZone#getDefault()
|
||||
*/
|
||||
public CronSequenceGenerator(String expression) {
|
||||
this(expression, TimeZone.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a {@link CronSequenceGenerator} from the pattern provided,
|
||||
* using the specified {@link TimeZone}.
|
||||
* @param expression a space-separated list of time fields
|
||||
* @param timeZone the TimeZone to use for generated trigger times
|
||||
* @throws IllegalArgumentException if the pattern cannot be parsed
|
||||
@@ -114,12 +126,17 @@ public class CronSequenceGenerator {
|
||||
calendar.setTimeZone(this.timeZone);
|
||||
calendar.setTime(date);
|
||||
|
||||
// Truncate to the next whole second
|
||||
calendar.add(Calendar.SECOND, 1);
|
||||
// First, just reset the milliseconds and try to calculate from there...
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
|
||||
long originalTimestamp = calendar.getTimeInMillis();
|
||||
doNext(calendar, calendar.get(Calendar.YEAR));
|
||||
|
||||
if (calendar.getTimeInMillis() == originalTimestamp) {
|
||||
// We arrived at the original timestamp - round up to the next whole second and try again...
|
||||
calendar.add(Calendar.SECOND, 1);
|
||||
doNext(calendar, calendar.get(Calendar.YEAR));
|
||||
}
|
||||
|
||||
return calendar.getTime();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -16,12 +16,12 @@
|
||||
|
||||
package org.springframework.scheduling.support;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.scheduling.Trigger;
|
||||
import org.springframework.scheduling.TriggerContext;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.TimeZone;
|
||||
|
||||
/**
|
||||
* {@link Trigger} implementation for cron expressions.
|
||||
* Wraps a {@link CronSequenceGenerator}.
|
||||
@@ -41,7 +41,7 @@ public class CronTrigger implements Trigger {
|
||||
* following cron expression conventions
|
||||
*/
|
||||
public CronTrigger(String cronExpression) {
|
||||
this(cronExpression, TimeZone.getDefault());
|
||||
this.sequenceGenerator = new CronSequenceGenerator(cronExpression);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -89,7 +89,7 @@ public class CronTrigger implements Trigger {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return sequenceGenerator.toString();
|
||||
return this.sequenceGenerator.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,8 +46,8 @@ import org.springframework.validation.annotation.Validated;
|
||||
* of that class. By default, JSR-303 will validate against its default group only.
|
||||
*
|
||||
* <p>As of Spring 3.1, this functionality requires Hibernate Validator 4.2 or higher.
|
||||
* In Spring 3.1.2, this class will autodetect a Bean Validation 1.1 compliant provider
|
||||
* and automatically use the standard method validation support there (once available).
|
||||
* Once Bean Validation 1.1 becomes available, this class will autodetect a compliant
|
||||
* provider and automatically use the standard method validation support there.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.1
|
||||
|
||||
@@ -130,7 +130,8 @@ public class SpringValidatorAdapter implements SmartValidator, javax.validation.
|
||||
}
|
||||
else {
|
||||
Object invalidValue = violation.getInvalidValue();
|
||||
if (field.contains(".") && !field.contains("[]")) {
|
||||
if (!"".equals(field) && (invalidValue == violation.getLeafBean() ||
|
||||
(field.contains(".") && !field.contains("[]")))) {
|
||||
// Possibly a bean constraint with property path: retrieve the actual property value.
|
||||
// However, explicitly avoid this for "address[]" style paths that we can't handle.
|
||||
invalidValue = bindingResult.getRawFieldValue(field);
|
||||
|
||||
@@ -44,7 +44,7 @@ import edu.emory.mathcs.backport.java.util.Collections;
|
||||
* @author Costin Leau
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class ExpressionEvalutatorTest {
|
||||
public class ExpressionEvaluatorTests {
|
||||
|
||||
@Rule
|
||||
public ExpectedException thrown = ExpectedException.none();
|
||||
@@ -16,7 +16,10 @@
|
||||
|
||||
package org.springframework.format.datetime;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
@@ -50,9 +53,12 @@ public class DateFormattingTests {
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
DefaultConversionService.addDefaultConverters(conversionService);
|
||||
|
||||
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
|
||||
setUp(registrar);
|
||||
}
|
||||
|
||||
private void setUp(DateFormatterRegistrar registrar) {
|
||||
DefaultConversionService.addDefaultConverters(conversionService);
|
||||
registrar.registerFormatters(conversionService);
|
||||
|
||||
SimpleDateBean bean = new SimpleDateBean();
|
||||
@@ -187,13 +193,48 @@ public class DateFormattingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateToString() throws Exception {
|
||||
public void dateToStringWithoutGlobalFormat() throws Exception {
|
||||
Date date = new Date();
|
||||
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
|
||||
String expected = date.toString();
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateToStringWithGlobalFormat() throws Exception {
|
||||
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
|
||||
registrar.setFormatter(new DateFormatter());
|
||||
setUp(registrar);
|
||||
Date date = new Date();
|
||||
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
|
||||
String expected = new DateFormatter().print(date, Locale.US);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void stringToDateWithoutGlobalFormat() throws Exception {
|
||||
// SPR-10105
|
||||
String string = "Sat, 12 Aug 1995 13:30:00 GM";
|
||||
Date date = this.conversionService.convert(string, Date.class);
|
||||
assertThat(date, equalTo(new Date(string)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringToDateWithGlobalFormat() throws Exception {
|
||||
// SPR-10105
|
||||
DateFormatterRegistrar registrar = new DateFormatterRegistrar();
|
||||
DateFormatter dateFormatter = new DateFormatter();
|
||||
dateFormatter.setIso(ISO.DATE_TIME);
|
||||
registrar.setFormatter(dateFormatter);
|
||||
setUp(registrar);
|
||||
// This is a format that cannot be parsed by new Date(String)
|
||||
String string = "2009-06-01T14:23:05.003+0000";
|
||||
Date date = this.conversionService.convert(string, Date.class);
|
||||
assertNotNull(date);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class SimpleDateBean {
|
||||
|
||||
|
||||
@@ -16,6 +16,11 @@
|
||||
|
||||
package org.springframework.format.datetime.joda;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
@@ -32,7 +37,6 @@ import org.joda.time.MutableDateTime;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.beans.MutablePropertyValues;
|
||||
import org.springframework.context.i18n.LocaleContextHolder;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
@@ -42,8 +46,6 @@ import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import org.springframework.format.support.FormattingConversionService;
|
||||
import org.springframework.validation.DataBinder;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
@@ -459,13 +461,40 @@ public class JodaTimeFormattingTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void dateToString() throws Exception {
|
||||
public void dateToStringWithFormat() throws Exception {
|
||||
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
|
||||
registrar.setDateTimeFormatter(org.joda.time.format.DateTimeFormat.shortDateTime());
|
||||
setUp(registrar);
|
||||
Date date = new Date();
|
||||
Object actual = this.conversionService.convert(date, TypeDescriptor.valueOf(Date.class), TypeDescriptor.valueOf(String.class));
|
||||
String expected = JodaTimeContextHolder.getFormatter(org.joda.time.format.DateTimeFormat.shortDateTime(), Locale.US).print(new DateTime(date));
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void stringToDateWithoutGlobalFormat() throws Exception {
|
||||
// SPR-10105
|
||||
String string = "Sat, 12 Aug 1995 13:30:00 GM";
|
||||
Date date = this.conversionService.convert(string, Date.class);
|
||||
assertThat(date, equalTo(new Date(string)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void stringToDateWithGlobalFormat() throws Exception {
|
||||
// SPR-10105
|
||||
JodaTimeFormatterRegistrar registrar = new JodaTimeFormatterRegistrar();
|
||||
DateTimeFormatterFactory factory = new DateTimeFormatterFactory();
|
||||
factory.setIso(ISO.DATE_TIME);
|
||||
registrar.setDateTimeFormatter(factory.createDateTimeFormatter());
|
||||
setUp(registrar);
|
||||
// This is a format that cannot be parsed by new Date(String)
|
||||
String string = "2009-10-31T07:00:00.000-05:00";
|
||||
Date date = this.conversionService.convert(string, Date.class);
|
||||
assertNotNull(date);
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class JodaTimeBean {
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -20,32 +20,38 @@ import javax.management.MBeanServer;
|
||||
import javax.management.MBeanServerFactory;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.tests.TestGroup;
|
||||
import org.springframework.util.MBeanTestUtils;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* <strong>Note:</strong> the JMX test suite requires the presence of the
|
||||
* {@code jmxremote_optional.jar} in your classpath. Thus, if you
|
||||
* run into the <em>"Unsupported protocol: jmxmp"</em> error, you will
|
||||
* need to download the
|
||||
* <a href="http://www.oracle.com/technetwork/java/javase/tech/download-jsp-141676.html">JMX Remote API 1.0.1_04 Reference Implementation</a>
|
||||
* from Oracle and extract {@code jmxremote_optional.jar} into your
|
||||
* classpath, for example in the {@code lib/ext} folder of your JVM.
|
||||
* <strong>Note:</strong> certain tests throughout this hierarchy require the presence of
|
||||
* the {@code jmxremote_optional.jar} in your classpath. For this reason, these tests are
|
||||
* run only if {@link TestGroup#JMXMP} is enabled. If you wish to run these tests, follow
|
||||
* the instructions in the TestGroup class to enable JMXMP tests. If you run into the
|
||||
* <em>"Unsupported protocol: jmxmp"</em> error, you will need to download the
|
||||
* <a href="http://www.oracle.com/technetwork/java/javase/tech/download-jsp-141676.html">
|
||||
* JMX Remote API 1.0.1_04 Reference Implementation</a> from Oracle and extract
|
||||
* {@code jmxremote_optional.jar} into your classpath, for example in the {@code lib/ext}
|
||||
* folder of your JVM.
|
||||
* See also <a href="https://issuetracker.springsource.com/browse/EBR-349">EBR-349</a>.
|
||||
*
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public abstract class AbstractMBeanServerTests extends TestCase {
|
||||
public abstract class AbstractMBeanServerTests {
|
||||
|
||||
protected MBeanServer server;
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public final void setUp() throws Exception {
|
||||
this.server = MBeanServerFactory.createMBeanServer();
|
||||
try {
|
||||
@@ -64,8 +70,8 @@ public abstract class AbstractMBeanServerTests extends TestCase {
|
||||
return ctx;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
releaseServer();
|
||||
onTearDown();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
@@ -29,18 +29,23 @@ import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
import org.springframework.jmx.IJmxTestBean;
|
||||
import org.springframework.jmx.JmxException;
|
||||
import org.springframework.jmx.JmxTestBean;
|
||||
import org.springframework.jmx.export.MBeanExporter;
|
||||
import org.springframework.jmx.export.assembler.AbstractReflectiveMBeanInfoAssembler;
|
||||
import org.springframework.tests.Assume;
|
||||
import org.springframework.tests.TestGroup;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
|
||||
@@ -78,6 +83,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
return (IJmxTestBean) factory.getObject();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testProxyClassIsDifferent() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -85,6 +91,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
assertTrue("The proxy class should be different than the base class", (proxy.getClass() != IJmxTestBean.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDifferentProxiesSameClass() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -95,6 +102,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
assertSame("The proxy classes should be the same", proxy1.getClass(), proxy2.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAttributeValue() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -103,6 +111,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
assertEquals("The age should be 100", 100, age);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAttributeValue() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -111,6 +120,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
assertEquals("The name of the bean should have been updated", "Rob Harrop", target.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAttributeValueWithRuntimeException() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -123,6 +133,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAttributeValueWithCheckedException() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -135,6 +146,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAttributeValueWithIOException() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -147,6 +159,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetReadOnlyAttribute() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -159,6 +172,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeNoArgs() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -167,6 +181,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
assertEquals("The operation should return 1", 1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeArgs() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -175,6 +190,7 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
assertEquals("The operation should return 3", 3, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInvokeUnexposedMethodWithException() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
@@ -187,19 +203,13 @@ public class MBeanClientInterceptorTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO [SPR-8089] Clean up ignored JMX tests.
|
||||
//
|
||||
// @Ignore should have no effect for JUnit 3.8 tests; however, it appears
|
||||
// that tests on the CI server -- as well as those in Eclipse -- do in
|
||||
// fact get ignored. So we leave @Ignore here so that developers can
|
||||
// easily search for ignored tests.
|
||||
//
|
||||
// Once fixed, renamed to test* instead of ignore*.
|
||||
@Ignore("Requires jmxremote_optional.jar; see comments in AbstractMBeanServerTests for details.")
|
||||
public void ignoreTestLazyConnectionToRemote() throws Exception {
|
||||
@Test
|
||||
public void testTestLazyConnectionToRemote() throws Exception {
|
||||
if (!runTests)
|
||||
return;
|
||||
|
||||
Assume.group(TestGroup.JMXMP);
|
||||
|
||||
JMXServiceURL url = new JMXServiceURL("service:jmx:jmxmp://localhost:9876");
|
||||
JMXConnectorServer connector = JMXConnectorServerFactory.newJMXConnectorServer(url, null, getServer());
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
@@ -26,19 +26,14 @@ import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.springframework.tests.Assume;
|
||||
import org.springframework.tests.TestGroup;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
// TODO [SPR-8089] Clean up ignored JMX tests.
|
||||
//
|
||||
// @Ignore should have no effect for JUnit 3.8 tests; however, it appears
|
||||
// that tests on the CI server -- as well as those in Eclipse -- do in
|
||||
// fact get ignored. So we leave @Ignore here so that developers can
|
||||
// easily search for ignored tests.
|
||||
@Ignore("Requires jmxremote_optional.jar; see comments in AbstractMBeanServerTests for details.")
|
||||
public class RemoteMBeanClientInterceptorTestsIgnore extends MBeanClientInterceptorTests {
|
||||
public class RemoteMBeanClientInterceptorTests extends MBeanClientInterceptorTests {
|
||||
|
||||
private static final String SERVICE_URL = "service:jmx:jmxmp://localhost:9876";
|
||||
|
||||
@@ -48,6 +43,9 @@ public class RemoteMBeanClientInterceptorTestsIgnore extends MBeanClientIntercep
|
||||
|
||||
@Override
|
||||
public void onSetUp() throws Exception {
|
||||
runTests = false;
|
||||
Assume.group(TestGroup.JMXMP);
|
||||
runTests = true;
|
||||
super.onSetUp();
|
||||
this.connectorServer = JMXConnectorServerFactory.newJMXConnectorServer(getServiceUrl(), null, getServer());
|
||||
try {
|
||||
@@ -73,8 +71,12 @@ public class RemoteMBeanClientInterceptorTestsIgnore extends MBeanClientIntercep
|
||||
if (this.connector != null) {
|
||||
this.connector.close();
|
||||
}
|
||||
this.connectorServer.stop();
|
||||
super.tearDown();
|
||||
if (this.connectorServer != null) {
|
||||
this.connectorServer.stop();
|
||||
}
|
||||
if (runTests) {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,8 +22,11 @@ import java.util.Date;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.jmx.AbstractJmxTests;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
*/
|
||||
@@ -36,6 +39,7 @@ public class CustomEditorConfigurerTests extends AbstractJmxTests {
|
||||
return "org/springframework/jmx/export/customConfigurer.xml";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDatesInJmx() throws Exception {
|
||||
// System.out.println(getServer().getClass().getName());
|
||||
ObjectName oname = new ObjectName("bean:name=dateRange");
|
||||
@@ -47,6 +51,7 @@ public class CustomEditorConfigurerTests extends AbstractJmxTests {
|
||||
assertEquals("endDate ", getEndDate(), endJmx);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDates() throws Exception {
|
||||
DateRange dr = (DateRange) getContext().getBean("dateRange");
|
||||
|
||||
|
||||
@@ -28,6 +28,8 @@ import org.springframework.jmx.JmxTestBean;
|
||||
import org.springframework.jmx.export.naming.ObjectNamingStrategy;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Juergen Hoeller
|
||||
|
||||
@@ -33,6 +33,7 @@ import javax.management.ObjectInstance;
|
||||
import javax.management.ObjectName;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
@@ -50,6 +51,8 @@ import org.springframework.jmx.support.RegistrationPolicy;
|
||||
import org.springframework.tests.aop.interceptor.NopInterceptor;
|
||||
import org.springframework.tests.sample.beans.TestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests for the {@link MBeanExporter} class.
|
||||
*
|
||||
@@ -66,6 +69,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
private static final String OBJECT_NAME = "spring:test=jmxMBeanAdaptor";
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNonNotificationListenerType() throws Exception {
|
||||
Map listeners = new HashMap();
|
||||
// put a non-NotificationListener instance in as a value...
|
||||
@@ -80,6 +84,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNullNotificationListenerType() throws Exception {
|
||||
Map listeners = new HashMap();
|
||||
// put null in as a value...
|
||||
@@ -94,6 +99,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNotificationListenerForNonExistentMBean() throws Exception {
|
||||
Map listeners = new HashMap();
|
||||
NotificationListener dummyListener = new NotificationListener() {
|
||||
@@ -117,6 +123,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithSuppliedMBeanServer() throws Exception {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setBeans(getBeanMap());
|
||||
@@ -127,6 +134,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
/** Fails if JVM platform MBean server has been started already
|
||||
@Test
|
||||
public void testWithLocatedMBeanServer() throws Exception {
|
||||
MBeanExporter adaptor = new MBeanExporter();
|
||||
adaptor.setBeans(getBeanMap());
|
||||
@@ -136,6 +144,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testUserCreatedMBeanRegWithDynamicMBean() throws Exception {
|
||||
Map<String, Object> map = new HashMap<String, Object>();
|
||||
map.put("spring:name=dynBean", new TestDynamicMBean());
|
||||
@@ -153,6 +162,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
assertFalse("Assembler should not have been invoked", asm.invoked);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetectMBeans() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource("autodetectMBeans.xml", getClass()));
|
||||
@@ -170,6 +180,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetectWithExclude() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource("autodetectMBeans.xml", getClass()));
|
||||
@@ -189,6 +200,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetectLazyMBeans() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource("autodetectLazyMBeans.xml", getClass()));
|
||||
@@ -210,6 +222,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutodetectNoMBeans() throws Exception {
|
||||
DefaultListableBeanFactory bf = new DefaultListableBeanFactory();
|
||||
new XmlBeanDefinitionReader(bf).loadBeanDefinitions(new ClassPathResource("autodetectNoMBeans.xml", getClass()));
|
||||
@@ -220,6 +233,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithMBeanExporterListeners() throws Exception {
|
||||
MockMBeanExporterListener listener1 = new MockMBeanExporterListener();
|
||||
MockMBeanExporterListener listener2 = new MockMBeanExporterListener();
|
||||
@@ -235,6 +249,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
assertListener(listener2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExportJdkProxy() throws Exception {
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
bean.setName("Rob Harrop");
|
||||
@@ -260,6 +275,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Rob Harrop", nameValue);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSelfNaming() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance(OBJECT_NAME);
|
||||
SelfNamingTestBean testBean = new SelfNamingTestBean();
|
||||
@@ -278,6 +294,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
assertNotNull(instance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterIgnoreExisting() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance(OBJECT_NAME);
|
||||
|
||||
@@ -311,6 +328,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Rob Harrop", server.getAttribute(objectName, "Name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterReplaceExisting() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance(OBJECT_NAME);
|
||||
|
||||
@@ -339,6 +357,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Sally Greenwood", server.getAttribute(objectName, "Name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithExposeClassLoader() throws Exception {
|
||||
String name = "Rob Harrop";
|
||||
String otherName = "Juergen Hoeller";
|
||||
@@ -368,6 +387,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Incorrect updated name.", otherName, bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBonaFideMBeanIsNotExportedWhenAutodetectIsTotallyTurnedOff() throws Exception {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
@@ -386,6 +406,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
exporter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnlyBonaFideMBeanIsExportedWhenAutodetectIsMBeanOnly() throws Exception {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
@@ -405,6 +426,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
ObjectNameManager.getInstance(exportedBeanName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBonaFideMBeanAndRegularBeanExporterWithAutodetectAll() throws Exception {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
@@ -428,6 +450,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
ObjectNameManager.getInstance(notToBeExportedBeanName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBonaFideMBeanIsNotExportedWithAutodetectAssembler() throws Exception {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
@@ -450,6 +473,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
/**
|
||||
* Want to ensure that said MBean is not exported twice.
|
||||
*/
|
||||
@Test
|
||||
public void testBonaFideMBeanExplicitlyExportedAndAutodetectionIsOn() throws Exception {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
|
||||
DefaultListableBeanFactory factory = new DefaultListableBeanFactory();
|
||||
@@ -468,6 +492,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
ObjectNameManager.getInstance(OBJECT_NAME));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeToOutOfRangeNegativeValue() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
@@ -478,6 +503,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeToOutOfRangePositiveValue() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
@@ -488,6 +514,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeNameToNull() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
@@ -498,6 +525,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeNameToAnEmptyString() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
@@ -508,6 +536,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeNameToAWhitespacedString() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
@@ -518,6 +547,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAutodetectModeNameToARubbishValue() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
@@ -528,6 +558,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotRunningInBeanFactoryAndPassedBeanNameToExport() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
@@ -541,6 +572,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotRunningInBeanFactoryAndAutodetectionIsOn() throws Exception {
|
||||
try {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
@@ -555,6 +587,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
/**
|
||||
* SPR-2158
|
||||
*/
|
||||
@Test
|
||||
public void testMBeanIsNotUnregisteredSpuriouslyIfSomeExternalProcessHasUnregisteredMBean() throws Exception {
|
||||
MBeanExporter exporter = new MBeanExporter();
|
||||
exporter.setBeans(getBeanMap());
|
||||
@@ -574,6 +607,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
/**
|
||||
* SPR-3302
|
||||
*/
|
||||
@Test
|
||||
public void testBeanNameCanBeUsedInNotificationListenersMap() throws Exception {
|
||||
String beanName = "charlesDexterWard";
|
||||
BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class);
|
||||
@@ -595,6 +629,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
exporter.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWildcardCanBeUsedInNotificationListenersMap() throws Exception {
|
||||
String beanName = "charlesDexterWard";
|
||||
BeanDefinitionBuilder testBean = BeanDefinitionBuilder.rootBeanDefinition(JmxTestBean.class);
|
||||
@@ -619,6 +654,7 @@ public final class MBeanExporterTests extends AbstractMBeanServerTests {
|
||||
/*
|
||||
* SPR-3625
|
||||
*/
|
||||
@Test
|
||||
public void testMBeanIsUnregisteredForRuntimeExceptionDuringInitialization() throws Exception {
|
||||
BeanDefinitionBuilder builder1 = BeanDefinitionBuilder.rootBeanDefinition(Person.class);
|
||||
BeanDefinitionBuilder builder2 = BeanDefinitionBuilder
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.management.NotificationFilter;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
import org.springframework.jmx.JmxTestBean;
|
||||
@@ -33,6 +34,8 @@ import org.springframework.jmx.access.NotificationListenerRegistrar;
|
||||
import org.springframework.jmx.export.naming.SelfNaming;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Mark Fisher
|
||||
@@ -41,6 +44,7 @@ import org.springframework.jmx.support.ObjectNameManager;
|
||||
public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
@Test
|
||||
public void testRegisterNotificationListenerForMBean() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
@@ -66,6 +70,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNotificationListenerWithWildcard() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
@@ -90,6 +95,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener not notified", 1, listener.getCount(attributeName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterNotificationListenerWithHandback() throws Exception {
|
||||
String objectName = "spring:name=Test";
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
@@ -120,6 +126,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Handback object not transmitted correctly", handback, listener.getLastHandback(attributeName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterNotificationListenerForAllMBeans() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
@@ -146,6 +153,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
@Test
|
||||
public void testRegisterNotificationListenerWithFilter() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
@@ -186,6 +194,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener incorrectly notified for Age", 0, listener.getCount(ageAttribute));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreationWithNoNotificationListenerSet() {
|
||||
try {
|
||||
new NotificationListenerBean().afterPropertiesSet();
|
||||
@@ -195,6 +204,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNotificationListenerWithBeanNameAndBeanNameInBeansMap() throws Exception {
|
||||
String beanName = "testBean";
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
@@ -225,6 +235,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNotificationListenerWithBeanNameAndBeanInstanceInBeansMap() throws Exception {
|
||||
String beanName = "testBean";
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
@@ -255,6 +266,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNotificationListenerWithBeanNameBeforeObjectNameMappedToSameBeanInstance() throws Exception {
|
||||
String beanName = "testBean";
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
@@ -286,6 +298,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNotificationListenerWithObjectNameBeforeBeanNameMappedToSameBeanInstance() throws Exception {
|
||||
String beanName = "testBean";
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
@@ -317,6 +330,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
@Test
|
||||
public void testRegisterNotificationListenerWithTwoBeanNamesMappedToDifferentBeanInstances() throws Exception {
|
||||
String beanName1 = "testBean1";
|
||||
String beanName2 = "testBean2";
|
||||
@@ -359,6 +373,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener not notified for testBean2", 2, listener.getCount("Age"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationListenerRegistrar() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
JmxTestBean bean = new JmxTestBean();
|
||||
@@ -391,6 +406,7 @@ public class NotificationListenerTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Listener notified after destruction", 1, listener.getCount(attributeName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationListenerRegistrarWithMultipleNames() throws Exception {
|
||||
ObjectName objectName = ObjectName.getInstance("spring:name=Test");
|
||||
ObjectName objectName2 = ObjectName.getInstance("spring:name=Test2");
|
||||
|
||||
@@ -32,12 +32,15 @@ import javax.management.NotificationBroadcasterSupport;
|
||||
import javax.management.NotificationListener;
|
||||
import javax.management.ReflectionException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
import org.springframework.jmx.export.notification.NotificationPublisher;
|
||||
import org.springframework.jmx.export.notification.NotificationPublisherAware;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests for the Spring JMX {@link NotificationPublisher} functionality.
|
||||
*
|
||||
@@ -48,6 +51,7 @@ public class NotificationPublisherTests extends AbstractMBeanServerTests {
|
||||
|
||||
private CountingNotificationListener listener = new CountingNotificationListener();
|
||||
|
||||
@Test
|
||||
public void testSimpleBean() throws Exception {
|
||||
// start the MBeanExporter
|
||||
ConfigurableApplicationContext ctx = loadContext("org/springframework/jmx/export/notificationPublisherTests.xml");
|
||||
@@ -60,6 +64,7 @@ public class NotificationPublisherTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Notification not sent", 1, listener.count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSimpleBeanRegisteredManually() throws Exception {
|
||||
// start the MBeanExporter
|
||||
ConfigurableApplicationContext ctx = loadContext("org/springframework/jmx/export/notificationPublisherTests.xml");
|
||||
@@ -74,6 +79,7 @@ public class NotificationPublisherTests extends AbstractMBeanServerTests {
|
||||
assertEquals("Notification not sent", 1, listener.count);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMBean() throws Exception {
|
||||
// start the MBeanExporter
|
||||
ConfigurableApplicationContext ctx = loadContext("org/springframework/jmx/export/notificationPublisherTests.xml");
|
||||
@@ -86,6 +92,7 @@ public class NotificationPublisherTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
|
||||
/*
|
||||
@Test
|
||||
public void testStandardMBean() throws Exception {
|
||||
// start the MBeanExporter
|
||||
ApplicationContext ctx = new ClassPathXmlApplicationContext("org/springframework/jmx/export/notificationPublisherTests.xml");
|
||||
@@ -97,6 +104,7 @@ public class NotificationPublisherTests extends AbstractMBeanServerTests {
|
||||
}
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testLazyInit() throws Exception {
|
||||
// start the MBeanExporter
|
||||
ConfigurableApplicationContext ctx = loadContext("org/springframework/jmx/export/notificationPublisherLazyTests.xml");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
@@ -18,11 +18,15 @@ package org.springframework.jmx.export;
|
||||
|
||||
import javax.management.ObjectName;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.jmx.AbstractJmxTests;
|
||||
import org.springframework.jmx.IJmxTestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class PropertyPlaceholderConfigurerTests extends AbstractJmxTests {
|
||||
|
||||
@@ -31,6 +35,7 @@ public class PropertyPlaceholderConfigurerTests extends AbstractJmxTests {
|
||||
return "org/springframework/jmx/export/propertyPlaceholderConfigurer.xml";
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertiesReplaced() {
|
||||
IJmxTestBean bean = (IJmxTestBean) getContext().getBean("testBean");
|
||||
|
||||
@@ -38,6 +43,7 @@ public class PropertyPlaceholderConfigurerTests extends AbstractJmxTests {
|
||||
assertEquals("Age is incorrect", 100, bean.getAge());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPropertiesCorrectInJmx() throws Exception {
|
||||
ObjectName oname = new ObjectName("bean:name=proxyTestBean1");
|
||||
Object name = getServer().getAttribute(oname, "Name");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
@@ -20,15 +20,22 @@ import javax.management.modelmbean.ModelMBeanInfo;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanOperationInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.jmx.IJmxTestBean;
|
||||
import org.springframework.jmx.export.assembler.AbstractMetadataAssemblerTests;
|
||||
import org.springframework.jmx.export.metadata.JmxAttributeSource;
|
||||
|
||||
/** @author Rob Harrop */
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerTests {
|
||||
|
||||
private static final String OBJECT_NAME = "bean:name=testBean4";
|
||||
|
||||
@Test
|
||||
public void testAttributeFromInterface() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = inf.getAttribute("Colour");
|
||||
@@ -36,12 +43,14 @@ public class AnnotationMetadataAssemblerTests extends AbstractMetadataAssemblerT
|
||||
assertTrue("The name attribute should be readable", attr.isReadable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationFromInterface() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanOperationInfo op = inf.getOperation("fromInterface");
|
||||
assertNotNull(op);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationOnGetter() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanOperationInfo op = inf.getOperation("getExpensiveToCalculate");
|
||||
|
||||
@@ -28,12 +28,16 @@ import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
import javax.management.modelmbean.ModelMBeanOperationInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.jmx.AbstractJmxTests;
|
||||
import org.springframework.jmx.IJmxTestBean;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
|
||||
@@ -43,12 +47,14 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
|
||||
protected abstract String getObjectName();
|
||||
|
||||
@Test
|
||||
public void testMBeanRegistration() throws Exception {
|
||||
// beans are registered at this point - just grab them from the server
|
||||
ObjectInstance instance = getObjectInstance();
|
||||
assertNotNull("Bean should not be null", instance);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterOperations() throws Exception {
|
||||
IJmxTestBean bean = getBean();
|
||||
assertNotNull(bean);
|
||||
@@ -57,6 +63,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
getExpectedOperationCount(), inf.getOperations().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterAttributes() throws Exception {
|
||||
IJmxTestBean bean = getBean();
|
||||
assertNotNull(bean);
|
||||
@@ -65,11 +72,13 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
getExpectedAttributeCount(), inf.getAttributes().length);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMBeanInfo() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
assertNotNull("MBeanInfo should not be null", info);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMBeanAttributeInfo() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
MBeanAttributeInfo[] inf = info.getAttributes();
|
||||
@@ -84,6 +93,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetMBeanOperationInfo() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
MBeanOperationInfo[] inf = info.getOperations();
|
||||
@@ -98,6 +108,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDescriptionNotNull() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
|
||||
@@ -105,6 +116,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
info.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetAttribute() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance(getObjectName());
|
||||
getServer().setAttribute(objectName, new Attribute(NAME_ATTRIBUTE, "Rob Harrop"));
|
||||
@@ -112,6 +124,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
assertEquals("Rob Harrop", bean.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAttribute() throws Exception {
|
||||
ObjectName objectName = ObjectNameManager.getInstance(getObjectName());
|
||||
getBean().setName("John Smith");
|
||||
@@ -119,6 +132,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
assertEquals("Incorrect result", "John Smith", val);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationInvocation() throws Exception{
|
||||
ObjectName objectName = ObjectNameManager.getInstance(getObjectName());
|
||||
Object result = getServer().invoke(objectName, "add",
|
||||
@@ -126,6 +140,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
assertEquals("Incorrect result", new Integer(50), result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttributeInfoHasDescriptors() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
|
||||
@@ -141,6 +156,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
desc.getFieldValue("setMethod"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttributeHasCorrespondingOperations() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
|
||||
@@ -159,6 +175,7 @@ public abstract class AbstractJmxAssemblerTests extends AbstractJmxTests {
|
||||
assertEquals("set operation should have role \"setter\"", "setter", set.getDescriptor().getFieldValue("role"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotificationMetadata() throws Exception {
|
||||
ModelMBeanInfo info = (ModelMBeanInfo) getMBeanInfo();
|
||||
MBeanNotificationInfo[] notifications = info.getNotifications();
|
||||
|
||||
@@ -26,6 +26,7 @@ import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
import javax.management.modelmbean.ModelMBeanOperationInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.framework.ProxyFactory;
|
||||
import org.springframework.jmx.IJmxTestBean;
|
||||
import org.springframework.jmx.JmxTestBean;
|
||||
@@ -34,6 +35,8 @@ import org.springframework.jmx.export.metadata.JmxAttributeSource;
|
||||
import org.springframework.jmx.support.ObjectNameManager;
|
||||
import org.springframework.tests.aop.interceptor.NopInterceptor;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
@@ -44,12 +47,14 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
|
||||
protected static final String CACHE_ENTRIES_METRIC = "CacheEntries";
|
||||
|
||||
@Test
|
||||
public void testDescription() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
assertEquals("The descriptions are not the same", "My Managed Bean",
|
||||
info.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttributeDescriptionOnSetter() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = inf.getAttribute(AGE_ATTRIBUTE);
|
||||
@@ -57,6 +62,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
"The Age Attribute", attr.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttributeDescriptionOnGetter() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = inf.getAttribute(NAME_ATTRIBUTE);
|
||||
@@ -67,12 +73,14 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
/**
|
||||
* Tests the situation where the attribute is only defined on the getter.
|
||||
*/
|
||||
@Test
|
||||
public void testReadOnlyAttribute() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = inf.getAttribute(AGE_ATTRIBUTE);
|
||||
assertFalse("The age attribute should not be writable", attr.isWritable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadWriteAttribute() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = inf.getAttribute(NAME_ATTRIBUTE);
|
||||
@@ -83,6 +91,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
/**
|
||||
* Tests the situation where the property only has a getter.
|
||||
*/
|
||||
@Test
|
||||
public void testWithOnlySetter() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = inf.getAttribute("NickName");
|
||||
@@ -92,12 +101,14 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
/**
|
||||
* Tests the situation where the property only has a setter.
|
||||
*/
|
||||
@Test
|
||||
public void testWithOnlyGetter() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute("Superman");
|
||||
assertNotNull("Attribute should not be null", attr);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testManagedResourceDescriptor() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
Descriptor desc = info.getMBeanDescriptor();
|
||||
@@ -111,6 +122,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
assertEquals("Persist Name should be bar", "bar.jmx", desc.getFieldValue("persistName"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttributeDescriptor() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
Descriptor desc = info.getAttribute(NAME_ATTRIBUTE).getDescriptor();
|
||||
@@ -121,6 +133,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
assertEquals("Persist Period should be 300", "300", desc.getFieldValue("persistPeriod"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationDescriptor() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
Descriptor desc = info.getOperation("myOperation").getDescriptor();
|
||||
@@ -129,6 +142,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
assertEquals("Role should be \"operation\"", "operation", desc.getFieldValue("role"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperationParameterMetadata() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanOperationInfo oper = info.getOperation("add");
|
||||
@@ -142,6 +156,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
assertEquals("Incorrect type for y param", int.class.getName(), params[1].getType());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithCglibProxy() throws Exception {
|
||||
IJmxTestBean tb = createJmxTestBean();
|
||||
ProxyFactory pf = new ProxyFactory();
|
||||
@@ -169,6 +184,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
assertTrue("Not included in autodetection", assembler.includeBean(proxy.getClass(), "some bean name"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetricDescription() throws Exception {
|
||||
ModelMBeanInfo inf = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo metric = inf.getAttribute(QUEUE_SIZE_METRIC);
|
||||
@@ -179,6 +195,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
"The QueueSize metric", operation.getDescription());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetricDescriptor() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
Descriptor desc = info.getAttribute(QUEUE_SIZE_METRIC).getDescriptor();
|
||||
@@ -191,6 +208,7 @@ public abstract class AbstractMetadataAssemblerTests extends AbstractJmxAssemble
|
||||
assertEquals("Metric Category should be utilization", "utilization",desc.getFieldValue("metricCategory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMetricDescriptorDefaults() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
Descriptor desc = info.getAttribute(CACHE_ENTRIES_METRIC).getDescriptor();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
@@ -19,8 +19,13 @@ package org.springframework.jmx.export.assembler;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class InterfaceBasedMBeanInfoAssemblerCustomTests extends AbstractJmxAssemblerTests {
|
||||
|
||||
@@ -48,6 +53,7 @@ public class InterfaceBasedMBeanInfoAssemblerCustomTests extends AbstractJmxAsse
|
||||
return assembler;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAgeIsReadOnly() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
|
||||
|
||||
@@ -22,13 +22,19 @@ import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class InterfaceBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAssemblerTests {
|
||||
|
||||
protected static final String OBJECT_NAME = "bean:name=testBean4";
|
||||
|
||||
@Test
|
||||
public void testGetAgeIsReadOnly() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
|
||||
@@ -37,6 +43,7 @@ public class InterfaceBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAsse
|
||||
assertFalse("Age is not writable", attr.isWritable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithUnknownClass() throws Exception {
|
||||
try {
|
||||
getWithMapping("com.foo.bar.Unknown");
|
||||
@@ -47,6 +54,7 @@ public class InterfaceBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAsse
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNonInterface() throws Exception {
|
||||
try {
|
||||
getWithMapping("JmxTestBean");
|
||||
@@ -57,7 +65,8 @@ public class InterfaceBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAsse
|
||||
}
|
||||
}
|
||||
|
||||
public void ignoreTestWithFallThrough() throws Exception {
|
||||
@Test
|
||||
public void testWithFallThrough() throws Exception {
|
||||
InterfaceBasedMBeanInfoAssembler assembler =
|
||||
getWithMapping("foobar", "org.springframework.jmx.export.assembler.ICustomJmxBean");
|
||||
assembler.setManagedInterfaces(new Class<?>[] {IAdditionalTestMethods.class});
|
||||
@@ -68,6 +77,7 @@ public class InterfaceBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAsse
|
||||
assertNickName(attr);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNickNameIsExposed() throws Exception {
|
||||
ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
|
||||
MBeanAttributeInfo attr = inf.getAttribute("NickName");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,14 +22,20 @@ import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class MethodExclusionMBeanInfoAssemblerComboTests extends AbstractJmxAssemblerTests {
|
||||
|
||||
protected static final String OBJECT_NAME = "bean:name=testBean4";
|
||||
|
||||
@Test
|
||||
public void testGetAgeIsReadOnly() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
|
||||
@@ -37,6 +43,7 @@ public class MethodExclusionMBeanInfoAssemblerComboTests extends AbstractJmxAsse
|
||||
assertFalse("Age is not writable", attr.isWritable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNickNameIsExposed() throws Exception {
|
||||
ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
|
||||
MBeanAttributeInfo attr = inf.getAttribute("NickName");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,13 +22,19 @@ import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class MethodExclusionMBeanInfoAssemblerMappedTests extends AbstractJmxAssemblerTests {
|
||||
|
||||
protected static final String OBJECT_NAME = "bean:name=testBean4";
|
||||
|
||||
@Test
|
||||
public void testGetAgeIsReadOnly() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
|
||||
@@ -36,6 +42,7 @@ public class MethodExclusionMBeanInfoAssemblerMappedTests extends AbstractJmxAss
|
||||
assertFalse("Age is not writable", attr.isWritable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNickNameIsExposed() throws Exception {
|
||||
ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
|
||||
MBeanAttributeInfo attr = inf.getAttribute("NickName");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,14 +22,20 @@ import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class MethodExclusionMBeanInfoAssemblerNotMappedTests extends AbstractJmxAssemblerTests {
|
||||
|
||||
protected static final String OBJECT_NAME = "bean:name=testBean4";
|
||||
|
||||
@Test
|
||||
public void testGetAgeIsReadOnly() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
|
||||
@@ -37,6 +43,7 @@ public class MethodExclusionMBeanInfoAssemblerNotMappedTests extends AbstractJmx
|
||||
assertTrue("Age is not writable", attr.isWritable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNickNameIsExposed() throws Exception {
|
||||
ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
|
||||
MBeanAttributeInfo attr = inf.getAttribute("NickName");
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -22,11 +22,15 @@ import java.util.Properties;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.jmx.JmxTestBean;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rick Evans
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class MethodExclusionMBeanInfoAssemblerTests extends AbstractJmxAssemblerTests {
|
||||
|
||||
@@ -60,6 +64,7 @@ public class MethodExclusionMBeanInfoAssemblerTests extends AbstractJmxAssembler
|
||||
return assembler;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSupermanIsReadOnly() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute("Superman");
|
||||
@@ -71,6 +76,7 @@ public class MethodExclusionMBeanInfoAssemblerTests extends AbstractJmxAssembler
|
||||
/*
|
||||
* http://opensource.atlassian.com/projects/spring/browse/SPR-2754
|
||||
*/
|
||||
@Test
|
||||
public void testIsNotIgnoredDoesntIgnoreUnspecifiedBeanMethods() throws Exception {
|
||||
final String beanKey = "myTestBean";
|
||||
MethodExclusionMBeanInfoAssembler assembler = new MethodExclusionMBeanInfoAssembler();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
@@ -16,18 +16,25 @@
|
||||
|
||||
package org.springframework.jmx.export.assembler;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.management.MBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class MethodNameBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAssemblerTests {
|
||||
|
||||
protected static final String OBJECT_NAME = "bean:name=testBean4";
|
||||
|
||||
@Test
|
||||
public void testGetAgeIsReadOnly() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
|
||||
@@ -36,6 +43,7 @@ public class MethodNameBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAss
|
||||
assertFalse("Age is not writable", attr.isWritable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithFallThrough() throws Exception {
|
||||
MethodNameBasedMBeanInfoAssembler assembler =
|
||||
getWithMapping("foobar", "add,myOperation,getName,setName,getAge");
|
||||
@@ -47,6 +55,7 @@ public class MethodNameBasedMBeanInfoAssemblerMappedTests extends AbstractJmxAss
|
||||
assertNickName(attr);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNickNameIsExposed() throws Exception {
|
||||
ModelMBeanInfo inf = (ModelMBeanInfo) getMBeanInfo();
|
||||
MBeanAttributeInfo attr = inf.getAttribute("NickName");
|
||||
|
||||
@@ -20,9 +20,14 @@ import javax.management.MBeanOperationInfo;
|
||||
import javax.management.modelmbean.ModelMBeanAttributeInfo;
|
||||
import javax.management.modelmbean.ModelMBeanInfo;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author David Boden
|
||||
* @author Chris Beams
|
||||
*/
|
||||
public class MethodNameBasedMBeanInfoAssemblerTests extends AbstractJmxAssemblerTests {
|
||||
|
||||
@@ -50,6 +55,7 @@ public class MethodNameBasedMBeanInfoAssemblerTests extends AbstractJmxAssembler
|
||||
return assembler;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetAgeIsReadOnly() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
ModelMBeanAttributeInfo attr = info.getAttribute(AGE_ATTRIBUTE);
|
||||
@@ -58,6 +64,7 @@ public class MethodNameBasedMBeanInfoAssemblerTests extends AbstractJmxAssembler
|
||||
assertFalse(attr.isWritable());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSetNameParameterIsNamed() throws Exception {
|
||||
ModelMBeanInfo info = getMBeanInfoFromAssembler();
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2011 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
|
||||
* use this file except in compliance with the License. You may obtain a copy of
|
||||
@@ -28,23 +28,36 @@ import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
import org.springframework.tests.Assume;
|
||||
import org.springframework.tests.TestGroup;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Chris Beams
|
||||
*/
|
||||
// TODO [SPR-8089] Clean up ignored JMX tests.
|
||||
//
|
||||
// @Ignore should have no effect for JUnit 3.8 tests; however, it appears
|
||||
// that tests on the CI server -- as well as those in Eclipse -- do in
|
||||
// fact get ignored. So we leave @Ignore here so that developers can
|
||||
// easily search for ignored tests.
|
||||
@Ignore("Requires jmxremote_optional.jar; see comments in AbstractMBeanServerTests for details.")
|
||||
public class ConnectorServerFactoryBeanTestsIgnore extends AbstractMBeanServerTests {
|
||||
public class ConnectorServerFactoryBeanTests extends AbstractMBeanServerTests {
|
||||
|
||||
private static final String OBJECT_NAME = "spring:type=connector,name=test";
|
||||
private boolean runTests = false;
|
||||
|
||||
@Override
|
||||
protected void onSetUp() throws Exception {
|
||||
Assume.group(TestGroup.JMXMP);
|
||||
runTests = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void tearDown() throws Exception {
|
||||
if (runTests) {
|
||||
super.tearDown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartupWithLocatedServer() throws Exception {
|
||||
ConnectorServerFactoryBean bean = new ConnectorServerFactoryBean();
|
||||
bean.afterPropertiesSet();
|
||||
@@ -56,6 +69,7 @@ public class ConnectorServerFactoryBeanTestsIgnore extends AbstractMBeanServerTe
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStartupWithSuppliedServer() throws Exception {
|
||||
//Added a brief snooze here - seems to fix occasional
|
||||
//java.net.BindException: Address already in use errors
|
||||
@@ -72,6 +86,7 @@ public class ConnectorServerFactoryBeanTestsIgnore extends AbstractMBeanServerTe
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegisterWithMBeanServer() throws Exception {
|
||||
//Added a brief snooze here - seems to fix occasional
|
||||
//java.net.BindException: Address already in use errors
|
||||
@@ -89,6 +104,7 @@ public class ConnectorServerFactoryBeanTestsIgnore extends AbstractMBeanServerTe
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoRegisterWithMBeanServer() throws Exception {
|
||||
ConnectorServerFactoryBean bean = new ConnectorServerFactoryBean();
|
||||
bean.afterPropertiesSet();
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,9 +23,13 @@ import javax.management.remote.JMXConnectorServer;
|
||||
import javax.management.remote.JMXConnectorServerFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.aop.support.AopUtils;
|
||||
import org.springframework.jmx.AbstractMBeanServerTests;
|
||||
import org.springframework.tests.Assume;
|
||||
import org.springframework.tests.TestGroup;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
@@ -43,16 +47,9 @@ public class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTe
|
||||
return JMXConnectorServerFactory.newJMXConnectorServer(getServiceUrl(), null, getServer());
|
||||
}
|
||||
|
||||
// TODO [SPR-8089] Clean up ignored JMX tests.
|
||||
//
|
||||
// @Ignore should have no effect for JUnit 3.8 tests; however, it appears
|
||||
// that tests on the CI server -- as well as those in Eclipse -- do in
|
||||
// fact get ignored. So we leave @Ignore here so that developers can
|
||||
// easily search for ignored tests.
|
||||
//
|
||||
// Once fixed, renamed to test* instead of ignore*.
|
||||
@Ignore("Requires jmxremote_optional.jar; see comments in AbstractMBeanServerTests for details.")
|
||||
public void ignoreTestValidConnection() throws Exception {
|
||||
@Test
|
||||
public void testTestValidConnection() throws Exception {
|
||||
Assume.group(TestGroup.JMXMP);
|
||||
JMXConnectorServer connectorServer = getConnectorServer();
|
||||
connectorServer.start();
|
||||
|
||||
@@ -75,6 +72,7 @@ public class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTe
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithNoServiceUrl() throws Exception {
|
||||
MBeanServerConnectionFactoryBean bean = new MBeanServerConnectionFactoryBean();
|
||||
try {
|
||||
@@ -85,16 +83,9 @@ public class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTe
|
||||
}
|
||||
}
|
||||
|
||||
// TODO [SPR-8089] Clean up ignored JMX tests.
|
||||
//
|
||||
// @Ignore should have no effect for JUnit 3.8 tests; however, it appears
|
||||
// that tests on the CI server -- as well as those in Eclipse -- do in
|
||||
// fact get ignored. So we leave @Ignore here so that developers can
|
||||
// easily search for ignored tests.
|
||||
//
|
||||
// Once fixed, renamed to test* instead of ignore*.
|
||||
@Ignore("Requires jmxremote_optional.jar; see comments in AbstractMBeanServerTests for details.")
|
||||
public void ignoreTestWithLazyConnection() throws Exception {
|
||||
@Test
|
||||
public void testTestWithLazyConnection() throws Exception {
|
||||
Assume.group(TestGroup.JMXMP);
|
||||
MBeanServerConnectionFactoryBean bean = new MBeanServerConnectionFactoryBean();
|
||||
bean.setServiceUrl(SERVICE_URL);
|
||||
bean.setConnectOnStartup(false);
|
||||
@@ -116,6 +107,7 @@ public class MBeanServerConnectionFactoryBeanTests extends AbstractMBeanServerTe
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithLazyConnectionAndNoAccess() throws Exception {
|
||||
MBeanServerConnectionFactoryBean bean = new MBeanServerConnectionFactoryBean();
|
||||
bean.setServiceUrl(SERVICE_URL);
|
||||
|
||||
@@ -66,6 +66,21 @@ public class AsyncExecutionTests {
|
||||
assertEquals("20", future.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMethodsThroughInterface() throws Exception {
|
||||
originalThreadName = Thread.currentThread().getName();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(SimpleAsyncMethodBean.class));
|
||||
context.registerBeanDefinition("autoProxyCreator", new RootBeanDefinition(DefaultAdvisorAutoProxyCreator.class));
|
||||
context.registerBeanDefinition("asyncAdvisor", new RootBeanDefinition(AsyncAnnotationAdvisor.class));
|
||||
context.refresh();
|
||||
SimpleInterface asyncTest = context.getBean("asyncTest", SimpleInterface.class);
|
||||
asyncTest.doNothing(5);
|
||||
asyncTest.doSomething(10);
|
||||
Future<String> future = asyncTest.returnSomething(20);
|
||||
assertEquals("20", future.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMethodsWithQualifier() throws Exception {
|
||||
originalThreadName = Thread.currentThread().getName();
|
||||
@@ -86,6 +101,26 @@ public class AsyncExecutionTests {
|
||||
assertEquals("30", future2.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncMethodsWithQualifierThroughInterface() throws Exception {
|
||||
originalThreadName = Thread.currentThread().getName();
|
||||
GenericApplicationContext context = new GenericApplicationContext();
|
||||
context.registerBeanDefinition("asyncTest", new RootBeanDefinition(SimpleAsyncMethodWithQualifierBean.class));
|
||||
context.registerBeanDefinition("autoProxyCreator", new RootBeanDefinition(DefaultAdvisorAutoProxyCreator.class));
|
||||
context.registerBeanDefinition("asyncAdvisor", new RootBeanDefinition(AsyncAnnotationAdvisor.class));
|
||||
context.registerBeanDefinition("e0", new RootBeanDefinition(ThreadPoolTaskExecutor.class));
|
||||
context.registerBeanDefinition("e1", new RootBeanDefinition(ThreadPoolTaskExecutor.class));
|
||||
context.registerBeanDefinition("e2", new RootBeanDefinition(ThreadPoolTaskExecutor.class));
|
||||
context.refresh();
|
||||
SimpleInterface asyncTest = context.getBean("asyncTest", SimpleInterface.class);
|
||||
asyncTest.doNothing(5);
|
||||
asyncTest.doSomething(10);
|
||||
Future<String> future = asyncTest.returnSomething(20);
|
||||
assertEquals("20", future.get());
|
||||
Future<String> future2 = asyncTest.returnSomething2(30);
|
||||
assertEquals("30", future2.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void asyncClass() throws Exception {
|
||||
originalThreadName = Thread.currentThread().getName();
|
||||
@@ -177,6 +212,18 @@ public class AsyncExecutionTests {
|
||||
}
|
||||
|
||||
|
||||
public interface SimpleInterface {
|
||||
|
||||
void doNothing(int i);
|
||||
|
||||
void doSomething(int i);
|
||||
|
||||
Future<String> returnSomething(int i);
|
||||
|
||||
Future<String> returnSomething2(int i);
|
||||
}
|
||||
|
||||
|
||||
public static class AsyncMethodBean {
|
||||
|
||||
public void doNothing(int i) {
|
||||
@@ -196,6 +243,15 @@ public class AsyncExecutionTests {
|
||||
}
|
||||
|
||||
|
||||
public static class SimpleAsyncMethodBean extends AsyncMethodBean implements SimpleInterface {
|
||||
|
||||
@Override
|
||||
public Future<String> returnSomething2(int i) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Async("e0")
|
||||
public static class AsyncMethodWithQualifierBean {
|
||||
|
||||
@@ -224,6 +280,10 @@ public class AsyncExecutionTests {
|
||||
}
|
||||
|
||||
|
||||
public static class SimpleAsyncMethodWithQualifierBean extends AsyncMethodWithQualifierBean implements SimpleInterface {
|
||||
}
|
||||
|
||||
|
||||
@Async("e2")
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyAsync {
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.scheduling.support;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class CronSequenceGeneratorTests {
|
||||
|
||||
@Test
|
||||
public void testAt50Seconds() {
|
||||
assertEquals(new Date(2012, 6, 2, 1, 0),
|
||||
new CronSequenceGenerator("*/15 * 1-4 * * *").next(new Date(2012, 6, 1, 9, 53, 50)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAt0Seconds() {
|
||||
assertEquals(new Date(2012, 6, 2, 1, 0),
|
||||
new CronSequenceGenerator("*/15 * 1-4 * * *").next(new Date(2012, 6, 1, 9, 53)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAt0Minutes() {
|
||||
assertEquals(new Date(2012, 6, 2, 1, 0),
|
||||
new CronSequenceGenerator("0 */2 1-4 * * *").next(new Date(2012, 6, 1, 9, 0)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -41,7 +41,7 @@ import static org.junit.Assert.*;
|
||||
@RunWith(Parameterized.class)
|
||||
public class CronTriggerTests {
|
||||
|
||||
private Calendar calendar = new GregorianCalendar();
|
||||
private final Calendar calendar = new GregorianCalendar();
|
||||
|
||||
private final Date date;
|
||||
|
||||
@@ -49,8 +49,8 @@ public class CronTriggerTests {
|
||||
|
||||
|
||||
public CronTriggerTests(Date date, TimeZone timeZone) {
|
||||
this.timeZone = timeZone;
|
||||
this.date = date;
|
||||
this.timeZone = timeZone;
|
||||
}
|
||||
|
||||
@Parameters
|
||||
@@ -66,6 +66,7 @@ public class CronTriggerTests {
|
||||
calendar.set(Calendar.MILLISECOND, 0);
|
||||
}
|
||||
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
calendar.setTimeZone(timeZone);
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.springframework.validation.Errors;
|
||||
import org.springframework.validation.FieldError;
|
||||
import org.springframework.validation.ObjectError;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
@@ -102,6 +103,20 @@ public class ValidatorFactoryTests {
|
||||
assertTrue(cv.getConstraintDescriptor().getAnnotation() instanceof NameAddressValid);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidationFieldType() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
validator.afterPropertiesSet();
|
||||
ValidPerson person = new ValidPerson();
|
||||
person.setName("Phil");
|
||||
person.getAddress().setStreet("Phil's Street");
|
||||
BeanPropertyBindingResult errors = new BeanPropertyBindingResult(person, "person");
|
||||
validator.validate(person, errors);
|
||||
assertEquals(1, errors.getErrorCount());
|
||||
assertThat("Field/Value type mismatch", errors.getFieldError("address").getRejectedValue(),
|
||||
instanceOf(ValidAddress.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSpringValidation() throws Exception {
|
||||
LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();
|
||||
@@ -289,8 +304,13 @@ public class ValidatorFactoryTests {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isValid(ValidPerson value, ConstraintValidatorContext constraintValidatorContext) {
|
||||
return (value.name == null || !value.address.street.contains(value.name));
|
||||
public boolean isValid(ValidPerson value, ConstraintValidatorContext context) {
|
||||
boolean valid = (value.name == null || !value.address.street.contains(value.name));
|
||||
if (!valid && "Phil".equals(value.name)) {
|
||||
context.buildConstraintViolationWithTemplate(
|
||||
context.getDefaultConstraintMessageTemplate()).addNode("address").addConstraintViolation().disableDefaultConstraintViolation();
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -369,8 +369,7 @@ public abstract class GenericTypeResolver {
|
||||
* all super types, enclosing types and interfaces.
|
||||
*/
|
||||
public static Map<TypeVariable, Type> getTypeVariableMap(Class clazz) {
|
||||
Map<TypeVariable, Type> ref = typeVariableCache.get(clazz);
|
||||
Map<TypeVariable, Type> typeVariableMap = (ref != null ? ref : null);
|
||||
Map<TypeVariable, Type> typeVariableMap = typeVariableCache.get(clazz);
|
||||
|
||||
if (typeVariableMap == null) {
|
||||
typeVariableMap = new HashMap<TypeVariable, Type>();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2009 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -18,6 +18,7 @@ package org.springframework.core.convert.support;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConverterFactory;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Converts from a String to a java.lang.Enum by calling {@link Enum#valueOf(Class, String)}.
|
||||
@@ -29,7 +30,13 @@ import org.springframework.core.convert.converter.ConverterFactory;
|
||||
final class StringToEnumConverterFactory implements ConverterFactory<String, Enum> {
|
||||
|
||||
public <T extends Enum> Converter<String, T> getConverter(Class<T> targetType) {
|
||||
return new StringToEnum(targetType);
|
||||
Class<?> enumType = targetType;
|
||||
while(enumType != null && !enumType.isEnum()) {
|
||||
enumType = enumType.getSuperclass();
|
||||
}
|
||||
Assert.notNull(enumType, "The target type " + targetType.getName()
|
||||
+ " does not refer to an enum");
|
||||
return new StringToEnum(enumType);
|
||||
}
|
||||
|
||||
private class StringToEnum<T extends Enum> implements Converter<String, T> {
|
||||
|
||||
@@ -88,10 +88,6 @@ public class SystemEnvironmentPropertySource extends MapPropertySource {
|
||||
public Object getProperty(String name) {
|
||||
Assert.notNull(name, "property name must not be null");
|
||||
String actualName = resolvePropertyName(name);
|
||||
if (actualName == null) {
|
||||
// at this point we know the property does not exist
|
||||
return null;
|
||||
}
|
||||
if (logger.isDebugEnabled() && !name.equals(actualName)) {
|
||||
logger.debug(String.format(
|
||||
"PropertySource [%s] does not contain '%s', but found equivalent '%s'",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -21,6 +21,7 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.springframework.asm.ClassReader;
|
||||
import org.springframework.core.NestedIOException;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.type.AnnotationMetadata;
|
||||
import org.springframework.core.type.ClassMetadata;
|
||||
@@ -47,10 +48,14 @@ final class SimpleMetadataReader implements MetadataReader {
|
||||
|
||||
SimpleMetadataReader(Resource resource, ClassLoader classLoader) throws IOException {
|
||||
InputStream is = new BufferedInputStream(resource.getInputStream());
|
||||
ClassReader classReader = null;
|
||||
ClassReader classReader;
|
||||
try {
|
||||
classReader = new ClassReader(is);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new NestedIOException("ASM ClassReader failed to parse class file - " +
|
||||
"probably due to a new Java class file version that isn't supported yet: " + resource, ex);
|
||||
}
|
||||
finally {
|
||||
is.close();
|
||||
}
|
||||
@@ -64,6 +69,7 @@ final class SimpleMetadataReader implements MetadataReader {
|
||||
this.resource = resource;
|
||||
}
|
||||
|
||||
|
||||
public Resource getResource() {
|
||||
return this.resource;
|
||||
}
|
||||
|
||||
@@ -317,7 +317,9 @@ public class AntPathMatcher implements PathMatcher {
|
||||
else if (!StringUtils.hasText(pattern2)) {
|
||||
return pattern1;
|
||||
}
|
||||
else if (!pattern1.equals(pattern2) && !pattern1.contains("{") && match(pattern1, pattern2)) {
|
||||
|
||||
boolean pattern1ContainsUriVar = pattern1.indexOf('{') != -1;
|
||||
if (!pattern1.equals(pattern2) && !pattern1ContainsUriVar && match(pattern1, pattern2)) {
|
||||
// /* + /hotel -> /hotel ; "/*.*" + "/*.html" -> /*.html
|
||||
// However /user + /user -> /usr/user ; /{foo} + /bar -> /{foo}/bar
|
||||
return pattern2;
|
||||
@@ -344,7 +346,7 @@ public class AntPathMatcher implements PathMatcher {
|
||||
}
|
||||
else {
|
||||
int dotPos1 = pattern1.indexOf('.');
|
||||
if (dotPos1 == -1) {
|
||||
if (dotPos1 == -1 || pattern1ContainsUriVar) {
|
||||
// simply concatenate the two patterns
|
||||
if (pattern1.endsWith("/") || pattern2.startsWith("/")) {
|
||||
return pattern1 + pattern2;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -31,19 +31,19 @@ import java.io.StringWriter;
|
||||
import java.io.Writer;
|
||||
|
||||
/**
|
||||
* Simple utility methods for file and stream copying.
|
||||
* All copy methods use a block size of 4096 bytes,
|
||||
* and close all affected streams when done.
|
||||
* Simple utility methods for file and stream copying. All copy methods use a block size
|
||||
* of 4096 bytes, and close all affected streams when done. A variation of the copy
|
||||
* methods from this class that leave streams open can be found in {@link StreamUtils}.
|
||||
*
|
||||
* <p>Mainly for use within the framework,
|
||||
* but also useful for application code.
|
||||
* <p>Mainly for use within the framework, but also useful for application code.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 06.10.2003
|
||||
* @see StreamUtils
|
||||
*/
|
||||
public abstract class FileCopyUtils {
|
||||
|
||||
public static final int BUFFER_SIZE = 4096;
|
||||
public static final int BUFFER_SIZE = StreamUtils.BUFFER_SIZE;
|
||||
|
||||
|
||||
//---------------------------------------------------------------------
|
||||
@@ -106,15 +106,7 @@ public abstract class FileCopyUtils {
|
||||
Assert.notNull(in, "No InputStream specified");
|
||||
Assert.notNull(out, "No OutputStream specified");
|
||||
try {
|
||||
int byteCount = 0;
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
int bytesRead = -1;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
byteCount += bytesRead;
|
||||
}
|
||||
out.flush();
|
||||
return byteCount;
|
||||
return StreamUtils.copy(in, out);
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
@@ -208,7 +200,7 @@ public abstract class FileCopyUtils {
|
||||
|
||||
/**
|
||||
* Copy the contents of the given String to the given output Writer.
|
||||
* Closes the write when done.
|
||||
* Closes the writer when done.
|
||||
* @param in the String to copy from
|
||||
* @param out the Writer to copy to
|
||||
* @throws IOException in case of I/O errors
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.FilterOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
|
||||
/**
|
||||
* Simple utility methods for dealing with streams. The copy methods of this class are
|
||||
* similar to those defined in {@link FileCopyUtils} except that all affected streams are
|
||||
* left open when done. All copy methods use a block size of 4096 bytes.
|
||||
*
|
||||
* <p>Mainly for use within the framework, but also useful for application code.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
* @since 3.2.2
|
||||
* @see FileCopyUtils
|
||||
*/
|
||||
public abstract class StreamUtils {
|
||||
|
||||
public static final int BUFFER_SIZE = 4096;
|
||||
|
||||
|
||||
/**
|
||||
* Copy the contents of the given InputStream into a new byte array.
|
||||
* Leaves the stream open when done.
|
||||
* @param in the stream to copy from
|
||||
* @return the new byte array that has been copied to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static byte[] copyToByteArray(InputStream in) throws IOException {
|
||||
ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
|
||||
copy(in, out);
|
||||
return out.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given InputStream into a String.
|
||||
* Leaves the stream open when done.
|
||||
* @param in the InputStream to copy from
|
||||
* @return the String that has been copied to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static String copyToString(InputStream in, Charset charset) throws IOException {
|
||||
Assert.notNull(in, "No InputStream specified");
|
||||
StringBuilder out = new StringBuilder();
|
||||
InputStreamReader reader = new InputStreamReader(in, charset);
|
||||
char[] buffer = new char[BUFFER_SIZE];
|
||||
int bytesRead = -1;
|
||||
while ((bytesRead = reader.read(buffer)) != -1) {
|
||||
out.append(buffer, 0, bytesRead);
|
||||
}
|
||||
return out.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given byte array to the given OutputStream.
|
||||
* Leaves the stream open when done.
|
||||
* @param in the byte array to copy from
|
||||
* @param out the OutputStream to copy to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static void copy(byte[] in, OutputStream out) throws IOException {
|
||||
Assert.notNull(in, "No input byte array specified");
|
||||
Assert.notNull(out, "No OutputStream specified");
|
||||
out.write(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given String to the given output OutputStream.
|
||||
* Leaves the stream open when done.
|
||||
* @param in the String to copy from
|
||||
* @param charset the Charset
|
||||
* @param out the OutputStream to copy to
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static void copy(String in, Charset charset, OutputStream out) throws IOException {
|
||||
Assert.notNull(in, "No input String specified");
|
||||
Assert.notNull(charset, "No charset specified");
|
||||
Assert.notNull(out, "No OutputStream specified");
|
||||
Writer writer = new OutputStreamWriter(out, charset);
|
||||
writer.write(in);
|
||||
writer.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy the contents of the given InputStream to the given OutputStream.
|
||||
* Leaves both streams open when done.
|
||||
* @param in the InputStream to copy from
|
||||
* @param out the OutputStream to copy to
|
||||
* @return the number of bytes copied
|
||||
* @throws IOException in case of I/O errors
|
||||
*/
|
||||
public static int copy(InputStream in, OutputStream out) throws IOException {
|
||||
Assert.notNull(in, "No InputStream specified");
|
||||
Assert.notNull(out, "No OutputStream specified");
|
||||
int byteCount = 0;
|
||||
byte[] buffer = new byte[BUFFER_SIZE];
|
||||
int bytesRead = -1;
|
||||
while ((bytesRead = in.read(buffer)) != -1) {
|
||||
out.write(buffer, 0, bytesRead);
|
||||
byteCount += bytesRead;
|
||||
}
|
||||
out.flush();
|
||||
return byteCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a variant of the given {@link InputStream} where calling
|
||||
* {@link InputStream#close() close()} has no effect.
|
||||
* @param in the InputStream to decorate
|
||||
* @return a version of the InputStream that ignores calls to close
|
||||
*/
|
||||
public static InputStream nonClosing(InputStream in) {
|
||||
Assert.notNull(in, "No InputStream specified");
|
||||
return new NonClosingInputStream(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a variant of the given {@link OutputStream} where calling
|
||||
* {@link OutputStream#close() close()} has no effect.
|
||||
* @param out the OutputStream to decorate
|
||||
* @return a version of the OutputStream that ignores calls to close
|
||||
*/
|
||||
public static OutputStream nonClosing(OutputStream out) {
|
||||
Assert.notNull(out, "No OutputStream specified");
|
||||
return new NonClosingOutputStream(out);
|
||||
}
|
||||
|
||||
|
||||
private static class NonClosingInputStream extends FilterInputStream {
|
||||
|
||||
public NonClosingInputStream(InputStream in) {
|
||||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class NonClosingOutputStream extends FilterOutputStream {
|
||||
|
||||
public NonClosingOutputStream(OutputStream out) {
|
||||
super(out);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(byte[] b, int off, int let) throws IOException {
|
||||
// It is critical that we override this method for performance
|
||||
out.write(b, off, let);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,24 +24,24 @@ import javax.xml.transform.sax.SAXResult;
|
||||
import org.xml.sax.ContentHandler;
|
||||
|
||||
/**
|
||||
* Implementation of the {@code Result} tagging interface for StAX writers. Can be constructed with a
|
||||
* {@code XMLEventConsumer} or a {@code XMLStreamWriter}.
|
||||
* Implementation of the {@code Result} tagging interface for StAX writers. Can be constructed with
|
||||
* an {@code XMLEventConsumer} or an {@code XMLStreamWriter}.
|
||||
*
|
||||
* <p>This class is necessary because there is no implementation of {@code Source} for StaxReaders in JAXP 1.3.
|
||||
* There is a {@code StAXResult} in JAXP 1.4 (JDK 1.6), but this class is kept around for back-ward compatibility
|
||||
* reasons.
|
||||
* <p>This class is necessary because there is no implementation of {@code Source} for StaxReaders
|
||||
* in JAXP 1.3. There is a {@code StAXResult} in JAXP 1.4 (JDK 1.6), but this class is kept around
|
||||
* for backwards compatibility reasons.
|
||||
*
|
||||
* <p>Even though {@code StaxResult} extends from {@code SAXResult}, calling the methods of
|
||||
* {@code SAXResult} is <strong>not supported</strong>. In general, the only supported operation on this class is
|
||||
* to use the {@code ContentHandler} obtained via {@link #getHandler()} to parse an input source using an
|
||||
* {@code XMLReader}. Calling {@link #setHandler(org.xml.sax.ContentHandler)} will result in
|
||||
* {@code UnsupportedOperationException}s.
|
||||
* {@code SAXResult} is <strong>not supported</strong>. In general, the only supported operation
|
||||
* on this class is to use the {@code ContentHandler} obtained via {@link #getHandler()} to parse an
|
||||
* input source using an {@code XMLReader}. Calling {@link #setHandler(org.xml.sax.ContentHandler)}
|
||||
* will result in {@code UnsupportedOperationException}s.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see XMLEventWriter
|
||||
* @see XMLStreamWriter
|
||||
* @see javax.xml.transform.Transformer
|
||||
* @since 3.0
|
||||
*/
|
||||
class StaxResult extends SAXResult {
|
||||
|
||||
@@ -49,9 +49,9 @@ class StaxResult extends SAXResult {
|
||||
|
||||
private XMLStreamWriter streamWriter;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the {@code StaxResult} with the specified {@code XMLStreamWriter}.
|
||||
*
|
||||
* Construct a new instance of the {@code StaxResult} with the specified {@code XMLStreamWriter}.
|
||||
* @param streamWriter the {@code XMLStreamWriter} to write to
|
||||
*/
|
||||
StaxResult(XMLStreamWriter streamWriter) {
|
||||
@@ -60,8 +60,7 @@ class StaxResult extends SAXResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the {@code StaxResult} with the specified {@code XMLEventWriter}.
|
||||
*
|
||||
* Construct a new instance of the {@code StaxResult} with the specified {@code XMLEventWriter}.
|
||||
* @param eventWriter the {@code XMLEventWriter} to write to
|
||||
*/
|
||||
StaxResult(XMLEventWriter eventWriter) {
|
||||
@@ -70,9 +69,8 @@ class StaxResult extends SAXResult {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the {@code StaxResult} with the specified {@code XMLEventWriter} and
|
||||
* {@code XMLEventFactory}.
|
||||
*
|
||||
* Construct a new instance of the {@code StaxResult} with the specified {@code XMLEventWriter}
|
||||
* and {@code XMLEventFactory}.
|
||||
* @param eventWriter the {@code XMLEventWriter} to write to
|
||||
* @param eventFactory the {@code XMLEventFactory} to use for creating events
|
||||
*/
|
||||
@@ -81,35 +79,35 @@ class StaxResult extends SAXResult {
|
||||
this.eventWriter = eventWriter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@code XMLEventWriter} used by this {@code StaxResult}. If this {@code StaxResult} was
|
||||
* created with an {@code XMLStreamWriter}, the result will be {@code null}.
|
||||
*
|
||||
* Return the {@code XMLEventWriter} used by this {@code StaxResult}. If this {@code StaxResult}
|
||||
* was created with an {@code XMLStreamWriter}, the result will be {@code null}.
|
||||
* @return the StAX event writer used by this result
|
||||
* @see #StaxResult(javax.xml.stream.XMLEventWriter)
|
||||
*/
|
||||
XMLEventWriter getXMLEventWriter() {
|
||||
return eventWriter;
|
||||
return this.eventWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code XMLStreamWriter} used by this {@code StaxResult}. If this {@code StaxResult} was
|
||||
* created with an {@code XMLEventConsumer}, the result will be {@code null}.
|
||||
*
|
||||
* Return the {@code XMLStreamWriter} used by this {@code StaxResult}. If this {@code StaxResult}
|
||||
* was created with an {@code XMLEventConsumer}, the result will be {@code null}.
|
||||
* @return the StAX stream writer used by this result
|
||||
* @see #StaxResult(javax.xml.stream.XMLStreamWriter)
|
||||
*/
|
||||
XMLStreamWriter getXMLStreamWriter() {
|
||||
return streamWriter;
|
||||
return this.streamWriter;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws a {@code UnsupportedOperationException}.
|
||||
*
|
||||
* Throws an {@code UnsupportedOperationException}.
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
@Override
|
||||
public void setHandler(ContentHandler handler) {
|
||||
throw new UnsupportedOperationException("setHandler is not supported");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -24,24 +24,24 @@ import org.xml.sax.InputSource;
|
||||
import org.xml.sax.XMLReader;
|
||||
|
||||
/**
|
||||
* Implementation of the {@code Source} tagging interface for StAX readers. Can be constructed with a
|
||||
* {@code XMLEventReader} or a {@code XMLStreamReader}.
|
||||
* Implementation of the {@code Source} tagging interface for StAX readers. Can be constructed with
|
||||
* an {@code XMLEventReader} or an {@code XMLStreamReader}.
|
||||
*
|
||||
* <p>This class is necessary because there is no implementation of {@code Source} for StAX Readers in JAXP 1.3.
|
||||
* There is a {@code StAXSource} in JAXP 1.4 (JDK 1.6), but this class is kept around for back-ward compatibility
|
||||
* reasons.
|
||||
* <p>This class is necessary because there is no implementation of {@code Source} for StAX Readers
|
||||
* in JAXP 1.3. There is a {@code StAXSource} in JAXP 1.4 (JDK 1.6), but this class is kept around
|
||||
* for backwards compatibility reasons.
|
||||
*
|
||||
* <p>Even though {@code StaxSource} extends from {@code SAXSource}, calling the methods of
|
||||
* {@code SAXSource} is <strong>not supported</strong>. In general, the only supported operation on this class is
|
||||
* to use the {@code XMLReader} obtained via {@link #getXMLReader()} to parse the input source obtained via {@link
|
||||
* #getInputSource()}. Calling {@link #setXMLReader(XMLReader)} or {@link #setInputSource(InputSource)} will result in
|
||||
* {@code UnsupportedOperationException}s.
|
||||
* {@code SAXSource} is <strong>not supported</strong>. In general, the only supported operation
|
||||
* on this class is to use the {@code XMLReader} obtained via {@link #getXMLReader()} to parse the
|
||||
* input source obtained via {@link #getInputSource()}. Calling {@link #setXMLReader(XMLReader)}
|
||||
* or {@link #setInputSource(InputSource)} will result in {@code UnsupportedOperationException}s.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.0
|
||||
* @see XMLEventReader
|
||||
* @see XMLStreamReader
|
||||
* @see javax.xml.transform.Transformer
|
||||
* @since 3.0
|
||||
*/
|
||||
class StaxSource extends SAXSource {
|
||||
|
||||
@@ -49,11 +49,11 @@ class StaxSource extends SAXSource {
|
||||
|
||||
private XMLStreamReader streamReader;
|
||||
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the {@code StaxSource} with the specified {@code XMLStreamReader}. The
|
||||
* supplied stream reader must be in {@code XMLStreamConstants.START_DOCUMENT} or
|
||||
* Construct a new instance of the {@code StaxSource} with the specified {@code XMLStreamReader}.
|
||||
* The supplied stream reader must be in {@code XMLStreamConstants.START_DOCUMENT} or
|
||||
* {@code XMLStreamConstants.START_ELEMENT} state.
|
||||
*
|
||||
* @param streamReader the {@code XMLStreamReader} to read from
|
||||
* @throws IllegalStateException if the reader is not at the start of a document or element
|
||||
*/
|
||||
@@ -63,10 +63,9 @@ class StaxSource extends SAXSource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new instance of the {@code StaxSource} with the specified {@code XMLEventReader}. The
|
||||
* supplied event reader must be in {@code XMLStreamConstants.START_DOCUMENT} or
|
||||
* Construct a new instance of the {@code StaxSource} with the specified {@code XMLEventReader}.
|
||||
* The supplied event reader must be in {@code XMLStreamConstants.START_DOCUMENT} or
|
||||
* {@code XMLStreamConstants.START_ELEMENT} state.
|
||||
*
|
||||
* @param eventReader the {@code XMLEventReader} to read from
|
||||
* @throws IllegalStateException if the reader is not at the start of a document or element
|
||||
*/
|
||||
@@ -75,31 +74,30 @@ class StaxSource extends SAXSource {
|
||||
this.eventReader = eventReader;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the {@code XMLEventReader} used by this {@code StaxSource}. If this {@code StaxSource} was
|
||||
* created with an {@code XMLStreamReader}, the result will be {@code null}.
|
||||
*
|
||||
* Return the {@code XMLEventReader} used by this {@code StaxSource}. If this {@code StaxSource}
|
||||
* was created with an {@code XMLStreamReader}, the result will be {@code null}.
|
||||
* @return the StAX event reader used by this source
|
||||
* @see StaxSource#StaxSource(javax.xml.stream.XMLEventReader)
|
||||
*/
|
||||
XMLEventReader getXMLEventReader() {
|
||||
return eventReader;
|
||||
return this.eventReader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code XMLStreamReader} used by this {@code StaxSource}. If this {@code StaxSource} was
|
||||
* created with an {@code XMLEventReader}, the result will be {@code null}.
|
||||
*
|
||||
* Return the {@code XMLStreamReader} used by this {@code StaxSource}. If this {@code StaxSource}
|
||||
* was created with an {@code XMLEventReader}, the result will be {@code null}.
|
||||
* @return the StAX event reader used by this source
|
||||
* @see StaxSource#StaxSource(javax.xml.stream.XMLEventReader)
|
||||
*/
|
||||
XMLStreamReader getXMLStreamReader() {
|
||||
return streamReader;
|
||||
return this.streamReader;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws a {@code UnsupportedOperationException}.
|
||||
*
|
||||
* Throws an {@code UnsupportedOperationException}.
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
@Override
|
||||
@@ -108,12 +106,12 @@ class StaxSource extends SAXSource {
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws a {@code UnsupportedOperationException}.
|
||||
*
|
||||
* Throws an {@code UnsupportedOperationException}.
|
||||
* @throws UnsupportedOperationException always
|
||||
*/
|
||||
@Override
|
||||
public void setXMLReader(XMLReader reader) {
|
||||
throw new UnsupportedOperationException("setXMLReader is not supported");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -45,14 +45,15 @@ import org.springframework.util.ClassUtils;
|
||||
*/
|
||||
public abstract class StaxUtils {
|
||||
|
||||
// JAXP 1.4 is only available on JDK 1.6+
|
||||
private static boolean jaxp14Available =
|
||||
ClassUtils.isPresent("javax.xml.transform.stax.StAXSource", StaxUtils.class.getClassLoader());
|
||||
|
||||
|
||||
// Stax Source
|
||||
|
||||
/**
|
||||
* Create a custom, non-JAXP 1.4 StAX {@link Source} for the given {@link XMLStreamReader}.
|
||||
*
|
||||
* @param streamReader the StAX stream reader
|
||||
* @return a source wrapping the {@code streamReader}
|
||||
*/
|
||||
@@ -62,9 +63,8 @@ public abstract class StaxUtils {
|
||||
|
||||
/**
|
||||
* Create a StAX {@link Source} for the given {@link XMLStreamReader}.
|
||||
*
|
||||
* <p>If JAXP 1.4 is available, this method returns a {@link StAXSource}; otherwise it returns a
|
||||
* custom StAX Source.
|
||||
* <p>If JAXP 1.4 is available, this method returns a {@link StAXSource};
|
||||
* otherwise it returns a custom StAX Source.
|
||||
* @param streamReader the StAX stream reader
|
||||
* @return a source wrapping the {@code streamReader}
|
||||
* @see #createCustomStaxSource(XMLStreamReader)
|
||||
@@ -80,7 +80,6 @@ public abstract class StaxUtils {
|
||||
|
||||
/**
|
||||
* Create a custom, non-JAXP 1.4 StAX {@link Source} for the given {@link XMLEventReader}.
|
||||
*
|
||||
* @param eventReader the StAX event reader
|
||||
* @return a source wrapping the {@code eventReader}
|
||||
*/
|
||||
@@ -90,9 +89,8 @@ public abstract class StaxUtils {
|
||||
|
||||
/**
|
||||
* Create a StAX {@link Source} for the given {@link XMLEventReader}.
|
||||
*
|
||||
* <p>If JAXP 1.4 is available, this method returns a {@link StAXSource}; otherwise it returns a
|
||||
* custom StAX Source.
|
||||
* <p>If JAXP 1.4 is available, this method returns a {@link StAXSource};
|
||||
* otherwise it returns a custom StAX Source.
|
||||
* @param eventReader the StAX event reader
|
||||
* @return a source wrapping the {@code eventReader}
|
||||
* @throws XMLStreamException in case of StAX errors
|
||||
@@ -116,11 +114,11 @@ public abstract class StaxUtils {
|
||||
return (source instanceof StaxSource || (jaxp14Available && Jaxp14StaxHandler.isStaxSource(source)));
|
||||
}
|
||||
|
||||
|
||||
// Stax Result
|
||||
|
||||
/**
|
||||
* Create a custom, non-JAXP 1.4 StAX {@link Result} for the given {@link XMLStreamWriter}.
|
||||
*
|
||||
* @param streamWriter the StAX stream writer
|
||||
* @return a source wrapping the {@code streamWriter}
|
||||
*/
|
||||
@@ -130,9 +128,8 @@ public abstract class StaxUtils {
|
||||
|
||||
/**
|
||||
* Create a StAX {@link Result} for the given {@link XMLStreamWriter}.
|
||||
*
|
||||
* <p>If JAXP 1.4 is available, this method returns a {@link StAXResult}; otherwise it returns a
|
||||
* custom StAX Result.
|
||||
* <p>If JAXP 1.4 is available, this method returns a {@link StAXResult};
|
||||
* otherwise it returns a custom StAX Result.
|
||||
* @param streamWriter the StAX stream writer
|
||||
* @return a result wrapping the {@code streamWriter}
|
||||
* @see #createCustomStaxResult(XMLStreamWriter)
|
||||
@@ -148,7 +145,6 @@ public abstract class StaxUtils {
|
||||
|
||||
/**
|
||||
* Create a custom, non-JAXP 1.4 StAX {@link Result} for the given {@link XMLEventWriter}.
|
||||
*
|
||||
* @param eventWriter the StAX event writer
|
||||
* @return a source wrapping the {@code eventWriter}
|
||||
*/
|
||||
@@ -158,7 +154,6 @@ public abstract class StaxUtils {
|
||||
|
||||
/**
|
||||
* Create a StAX {@link Result} for the given {@link XMLEventWriter}.
|
||||
*
|
||||
* <p>If JAXP 1.4 is available, this method returns a {@link StAXResult}; otherwise it returns a
|
||||
* custom StAX Result.
|
||||
* @param eventWriter the StAX event writer
|
||||
@@ -177,8 +172,8 @@ public abstract class StaxUtils {
|
||||
|
||||
/**
|
||||
* Indicate whether the given {@link javax.xml.transform.Result} is a StAX Result.
|
||||
* @return {@code true} if {@code result} is a custom Stax Result or JAXP
|
||||
* 1.4 {@link StAXResult}; {@code false} otherwise.
|
||||
* @return {@code true} if {@code result} is a custom Stax Result or JAXP 1.4
|
||||
* {@link StAXResult}; {@code false} otherwise.
|
||||
*/
|
||||
public static boolean isStaxResult(Result result) {
|
||||
return (result instanceof StaxResult || (jaxp14Available && Jaxp14StaxHandler.isStaxResult(result)));
|
||||
@@ -327,6 +322,7 @@ public abstract class StaxUtils {
|
||||
return new XMLEventStreamWriter(eventWriter, eventFactory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Inner class to avoid a static JAXP 1.4 dependency.
|
||||
*/
|
||||
@@ -349,11 +345,11 @@ public abstract class StaxUtils {
|
||||
}
|
||||
|
||||
private static boolean isStaxSource(Source source) {
|
||||
return source instanceof StAXSource;
|
||||
return (source instanceof StAXSource);
|
||||
}
|
||||
|
||||
private static boolean isStaxResult(Result result) {
|
||||
return result instanceof StAXResult;
|
||||
return (result instanceof StAXResult);
|
||||
}
|
||||
|
||||
private static XMLStreamReader getXMLStreamReader(Source source) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.core.convert.support;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertArrayEquals;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -212,6 +213,11 @@ public class DefaultConversionTests {
|
||||
assertEquals(Foo.BAR, conversionService.convert("BAR", Foo.class));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringToEnumWithSubclss() throws Exception {
|
||||
assertEquals(SubFoo.BAZ, conversionService.convert("BAZ", SubFoo.BAR.getClass()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringToEnumEmptyString() {
|
||||
assertEquals(null, conversionService.convert("", Foo.class));
|
||||
@@ -226,6 +232,24 @@ public class DefaultConversionTests {
|
||||
BAR, BAZ;
|
||||
}
|
||||
|
||||
public static enum SubFoo {
|
||||
|
||||
BAR {
|
||||
@Override
|
||||
String s() {
|
||||
return "x";
|
||||
}
|
||||
},
|
||||
BAZ {
|
||||
@Override
|
||||
String s() {
|
||||
return "y";
|
||||
}
|
||||
};
|
||||
|
||||
abstract String s();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringToLocale() {
|
||||
assertEquals(Locale.ENGLISH, conversionService.convert("en", Locale.class));
|
||||
|
||||
@@ -21,6 +21,10 @@ import java.util.EnumSet;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static java.lang.String.*;
|
||||
|
||||
/**
|
||||
* A test group used to limit when certain tests are run.
|
||||
*
|
||||
@@ -44,7 +48,13 @@ public enum TestGroup {
|
||||
* {@code StopWatch}, etc. should be considered a candidate as their successful
|
||||
* execution is likely to be based on events occurring within a given time window.
|
||||
*/
|
||||
PERFORMANCE;
|
||||
PERFORMANCE,
|
||||
|
||||
/**
|
||||
* Tests requiring the presence of jmxremote_optional.jar in jre/lib/ext in order to
|
||||
* avoid "Unsupported protocol: jmxmp" errors.
|
||||
*/
|
||||
JMXMP;
|
||||
|
||||
|
||||
/**
|
||||
@@ -64,8 +74,10 @@ public enum TestGroup {
|
||||
try {
|
||||
groups.add(valueOf(group.trim().toUpperCase()));
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("Unable to find test group '" + group.trim()
|
||||
+ "' when parsing '" + value + "'");
|
||||
throw new IllegalArgumentException(format(
|
||||
"Unable to find test group '%s' when parsing testGroups value: '%s'. " +
|
||||
"Available groups include: [%s]", group.trim(), value,
|
||||
StringUtils.arrayToCommaDelimitedString(TestGroup.values())));
|
||||
}
|
||||
}
|
||||
return groups;
|
||||
|
||||
@@ -62,7 +62,9 @@ public class TestGroupTests {
|
||||
@Test
|
||||
public void parseMissing() throws Exception {
|
||||
thrown.expect(IllegalArgumentException.class);
|
||||
thrown.expectMessage("Unable to find test group 'missing' when parsing 'performance, missing'");
|
||||
thrown.expectMessage("Unable to find test group 'missing' when parsing " +
|
||||
"testGroups value: 'performance, missing'. Available groups include: " +
|
||||
"[LONG_RUNNING,PERFORMANCE,JMXMP]");
|
||||
TestGroup.parse("performance, missing");
|
||||
}
|
||||
|
||||
|
||||
@@ -412,6 +412,7 @@ public class AntPathMatcherTests {
|
||||
assertEquals("/*.html", pathMatcher.combine("/*.*", "/*.html"));
|
||||
assertEquals("/{foo}/bar", pathMatcher.combine("/{foo}", "/bar")); // SPR-8858
|
||||
assertEquals("/user/user", pathMatcher.combine("/user", "/user")); // SPR-7970
|
||||
assertEquals("/{foo:.*[^0-9].*}/edit/", pathMatcher.combine("/{foo:.*[^0-9].*}", "/edit/")); // SPR-10062
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.inOrder;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.Random;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.InOrder;
|
||||
|
||||
/**
|
||||
* Tests for {@link StreamUtils}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
*/
|
||||
public class StreamUtilsTests {
|
||||
|
||||
private byte[] bytes = new byte[StreamUtils.BUFFER_SIZE + 10];
|
||||
|
||||
private String string = "";
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
new Random().nextBytes(bytes);
|
||||
while (string.length() < StreamUtils.BUFFER_SIZE + 10) {
|
||||
string += UUID.randomUUID().toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyToByteArray() throws Exception {
|
||||
InputStream inputStream = spy(new ByteArrayInputStream(bytes));
|
||||
byte[] actual = StreamUtils.copyToByteArray(inputStream);
|
||||
assertThat(actual, equalTo(bytes));
|
||||
verify(inputStream, never()).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyToString() throws Exception {
|
||||
Charset charset = Charset.defaultCharset();
|
||||
InputStream inputStream = spy(new ByteArrayInputStream(string.getBytes(charset)));
|
||||
String actual = StreamUtils.copyToString(inputStream, charset);
|
||||
assertThat(actual, equalTo(string));
|
||||
verify(inputStream, never()).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyBytes() throws Exception {
|
||||
ByteArrayOutputStream out = spy(new ByteArrayOutputStream());
|
||||
StreamUtils.copy(bytes, out);
|
||||
assertThat(out.toByteArray(), equalTo(bytes));
|
||||
verify(out, never()).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyString() throws Exception {
|
||||
Charset charset = Charset.defaultCharset();
|
||||
ByteArrayOutputStream out = spy(new ByteArrayOutputStream());
|
||||
StreamUtils.copy(string, charset, out);
|
||||
assertThat(out.toByteArray(), equalTo(string.getBytes(charset)));
|
||||
verify(out, never()).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void copyStream() throws Exception {
|
||||
ByteArrayOutputStream out = spy(new ByteArrayOutputStream());
|
||||
StreamUtils.copy(new ByteArrayInputStream(bytes), out);
|
||||
assertThat(out.toByteArray(), equalTo(bytes));
|
||||
verify(out, never()).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonClosingInputStream() throws Exception {
|
||||
InputStream source = mock(InputStream.class);
|
||||
InputStream nonClosing = StreamUtils.nonClosing(source);
|
||||
nonClosing.read();
|
||||
nonClosing.read(bytes);
|
||||
nonClosing.read(bytes, 1, 2);
|
||||
nonClosing.close();
|
||||
InOrder ordered = inOrder(source);
|
||||
ordered.verify(source).read();
|
||||
ordered.verify(source).read(bytes, 0, bytes.length);
|
||||
ordered.verify(source).read(bytes, 1, 2);
|
||||
ordered.verify(source, never()).close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void nonClosingOutputStream() throws Exception {
|
||||
OutputStream source = mock(OutputStream.class);
|
||||
OutputStream nonClosing = StreamUtils.nonClosing(source);
|
||||
nonClosing.write(1);
|
||||
nonClosing.write(bytes);
|
||||
nonClosing.write(bytes, 1, 2);
|
||||
nonClosing.close();
|
||||
InOrder ordered = inOrder(source);
|
||||
ordered.verify(source).write(1);
|
||||
ordered.verify(source).write(bytes, 0, bytes.length);
|
||||
ordered.verify(source).write(bytes, 1, 2);
|
||||
ordered.verify(source, never()).close();
|
||||
}
|
||||
}
|
||||
@@ -109,7 +109,8 @@ public enum SpelMessage {
|
||||
OPERAND_NOT_DECREMENTABLE(Kind.ERROR,1067,"the expression component ''{0}'' does not support decrement"), //
|
||||
NOT_ASSIGNABLE(Kind.ERROR,1068,"the expression component ''{0}'' is not assignable"), //
|
||||
MISSING_CHARACTER(Kind.ERROR,1069,"missing expected character ''{0}''"),
|
||||
LEFT_OPERAND_PROBLEM(Kind.ERROR,1070, "Problem parsing left operand");
|
||||
LEFT_OPERAND_PROBLEM(Kind.ERROR,1070, "Problem parsing left operand"),
|
||||
MISSING_SELECTION_EXPRESSION(Kind.ERROR, 1071, "A required selection expression has not been specified");
|
||||
|
||||
private Kind kind;
|
||||
private int code;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -29,6 +29,7 @@ import org.springframework.expression.TypedValue;
|
||||
import org.springframework.expression.spel.ExpressionState;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
@@ -54,7 +55,9 @@ public class Selection extends SpelNodeImpl {
|
||||
private final boolean nullSafe;
|
||||
|
||||
public Selection(boolean nullSafe, int variant,int pos,SpelNodeImpl expression) {
|
||||
super(pos,expression);
|
||||
super(pos, expression != null ? new SpelNodeImpl[] { expression }
|
||||
: new SpelNodeImpl[] {});
|
||||
Assert.notNull(expression, "Expression must not be null");
|
||||
this.nullSafe = nullSafe;
|
||||
this.variant = variant;
|
||||
}
|
||||
|
||||
@@ -557,6 +557,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
|
||||
}
|
||||
nextToken();
|
||||
SpelNodeImpl expr = eatExpression();
|
||||
if(expr == null) {
|
||||
raiseInternalException(toPos(t), SpelMessage.MISSING_SELECTION_EXPRESSION);
|
||||
}
|
||||
eatToken(TokenKind.RSQUARE);
|
||||
if (t.kind==TokenKind.SELECT_FIRST) {
|
||||
constructedNodes.push(new Selection(nullSafeNavigation,Selection.FIRST,toPos(t),expr));
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -19,13 +19,16 @@ package org.springframework.expression.spel.support;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.core.BridgeMethodResolver;
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.expression.AccessException;
|
||||
@@ -37,7 +40,6 @@ import org.springframework.expression.MethodResolver;
|
||||
import org.springframework.expression.TypeConverter;
|
||||
import org.springframework.expression.spel.SpelEvaluationException;
|
||||
import org.springframework.expression.spel.SpelMessage;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* Reflection-based {@link MethodResolver} used by default in
|
||||
@@ -92,25 +94,16 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
try {
|
||||
TypeConverter typeConverter = context.getTypeConverter();
|
||||
Class<?> type = (targetObject instanceof Class ? (Class<?>) targetObject : targetObject.getClass());
|
||||
Method[] methods = getMethods(type, targetObject);
|
||||
List<Method> methods = new ArrayList<Method>(Arrays.asList(getMethods(type, targetObject)));
|
||||
|
||||
// If a filter is registered for this type, call it
|
||||
MethodFilter filter = (this.filters != null ? this.filters.get(type) : null);
|
||||
if (filter != null) {
|
||||
List<Method> methodsForFiltering = new ArrayList<Method>();
|
||||
for (Method method: methods) {
|
||||
methodsForFiltering.add(method);
|
||||
}
|
||||
List<Method> methodsFiltered = filter.filter(methodsForFiltering);
|
||||
if (CollectionUtils.isEmpty(methodsFiltered)) {
|
||||
methods = NO_METHODS;
|
||||
}
|
||||
else {
|
||||
methods = methodsFiltered.toArray(new Method[methodsFiltered.size()]);
|
||||
}
|
||||
methods = filter.filter(methods);
|
||||
}
|
||||
|
||||
Arrays.sort(methods, new Comparator<Method>() {
|
||||
// Sort methods into a sensible order
|
||||
Collections.sort(methods, new Comparator<Method>() {
|
||||
public int compare(Method m1, Method m2) {
|
||||
int m1pl = m1.getParameterTypes().length;
|
||||
int m2pl = m2.getParameterTypes().length;
|
||||
@@ -118,6 +111,14 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
}
|
||||
});
|
||||
|
||||
// Resolve any bridge methods
|
||||
for (int i = 0; i < methods.size(); i++) {
|
||||
methods.set(i, BridgeMethodResolver.findBridgedMethod(methods.get(i)));
|
||||
}
|
||||
|
||||
// Remove duplicate methods (possible due to resolved bridge methods)
|
||||
methods = new ArrayList<Method>(new LinkedHashSet<Method>(methods));
|
||||
|
||||
Method closeMatch = null;
|
||||
int closeMatchDistance = Integer.MAX_VALUE;
|
||||
int[] argsToConvert = null;
|
||||
@@ -125,9 +126,6 @@ public class ReflectiveMethodResolver implements MethodResolver {
|
||||
boolean multipleOptions = false;
|
||||
|
||||
for (Method method : methods) {
|
||||
if (method.isBridge()) {
|
||||
continue;
|
||||
}
|
||||
if (method.getName().equals(name)) {
|
||||
Class<?>[] paramTypes = method.getParameterTypes();
|
||||
List<TypeDescriptor> paramDescriptors = new ArrayList<TypeDescriptor>(paramTypes.length);
|
||||
|
||||
@@ -27,6 +27,7 @@ import static org.junit.Assert.fail;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
@@ -1736,6 +1737,22 @@ public class SpelReproTests extends ExpressionTestCase {
|
||||
assertThat(fromClass, is("interfaceValue"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR_10210() throws Exception {
|
||||
StandardEvaluationContext context = new StandardEvaluationContext();
|
||||
context.setVariable("bridgeExample", new org.springframework.expression.spel.spr10210.D());
|
||||
Expression parseExpression = parser.parseExpression("#bridgeExample.bridgeMethod()");
|
||||
parseExpression.getValue(context);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void SPR_10328() throws Exception {
|
||||
thrown.expect(SpelParseException.class);
|
||||
thrown.expectMessage("EL1071E:(pos 2): A required selection expression has not been specified");
|
||||
Expression exp = parser.parseExpression("$[]");
|
||||
exp.getValue(Arrays.asList("foo", "bar", "baz"));
|
||||
}
|
||||
|
||||
public static class BooleanHolder {
|
||||
|
||||
private Boolean simpleProperty = true;
|
||||
@@ -1796,4 +1813,5 @@ public class SpelReproTests extends ExpressionTestCase {
|
||||
|
||||
public static class StaticFinalImpl2 extends AbstractStaticFinal {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.spr10210;
|
||||
|
||||
import org.springframework.expression.spel.spr10210.comp.B;
|
||||
import org.springframework.expression.spel.spr10210.infra.C;
|
||||
|
||||
abstract class A extends B<C> {
|
||||
|
||||
public void bridgeMethod() {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.spr10210;
|
||||
|
||||
public class D extends A {
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.spr10210.comp;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.springframework.expression.spel.spr10210.infra.C;
|
||||
|
||||
public class B<T extends C> implements Serializable {
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.expression.spel.spr10210.infra;
|
||||
|
||||
public interface C {
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -133,7 +133,8 @@ public interface JdbcOperations {
|
||||
* object via a RowMapper.
|
||||
* <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
|
||||
* execute a static query with a PreparedStatement, use the overloaded
|
||||
* {@code queryForObject} method with {@code null} as argument array.
|
||||
* {@link #queryForObject(String, RowMapper, Object...)} method with
|
||||
* {@code null} as argument array.
|
||||
* @param sql SQL query to execute
|
||||
* @param rowMapper object that will map one object per row
|
||||
* @return the single mapped object
|
||||
@@ -148,7 +149,8 @@ public interface JdbcOperations {
|
||||
* Execute a query for a result object, given static SQL.
|
||||
* <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
|
||||
* execute a static query with a PreparedStatement, use the overloaded
|
||||
* {@code queryForObject} method with {@code null} as argument array.
|
||||
* {@link #queryForObject(String, Class, Object...)} method with
|
||||
* {@code null} as argument array.
|
||||
* <p>This method is useful for running static SQL with a known outcome.
|
||||
* The query is expected to be a single row/single column query; the returned
|
||||
* result will be directly mapped to the corresponding object type.
|
||||
@@ -166,7 +168,8 @@ public interface JdbcOperations {
|
||||
* Execute a query for a result Map, given static SQL.
|
||||
* <p>Uses a JDBC Statement, not a PreparedStatement. If you want to
|
||||
* execute a static query with a PreparedStatement, use the overloaded
|
||||
* {@code queryForMap} method with {@code null} as argument array.
|
||||
* {@link #queryForMap(String, Object...)} method with {@code null}
|
||||
* as argument array.
|
||||
* <p>The query is expected to be a single row query; the result row will be
|
||||
* mapped to a Map (one entry for each column, using the column name as the key).
|
||||
* @param sql SQL query to execute
|
||||
@@ -194,7 +197,9 @@ public interface JdbcOperations {
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws DataAccessException if there is any problem executing the query
|
||||
* @see #queryForLong(String, Object[])
|
||||
* @deprecated in favor of {@link #queryForObject(String, Class)}
|
||||
*/
|
||||
@Deprecated
|
||||
long queryForLong(String sql) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -211,7 +216,9 @@ public interface JdbcOperations {
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws DataAccessException if there is any problem executing the query
|
||||
* @see #queryForInt(String, Object[])
|
||||
* @deprecated in favor of {@link #queryForObject(String, Class)}
|
||||
*/
|
||||
@Deprecated
|
||||
int queryForInt(String sql) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -712,7 +719,9 @@ public interface JdbcOperations {
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see #queryForLong(String)
|
||||
* @see java.sql.Types
|
||||
* @deprecated in favor of {@link #queryForObject(String, Object[], int[], Class)} )}
|
||||
*/
|
||||
@Deprecated
|
||||
long queryForLong(String sql, Object[] args, int[] argTypes) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -730,7 +739,9 @@ public interface JdbcOperations {
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see #queryForLong(String)
|
||||
* @deprecated in favor of {@link #queryForObject(String, Class, Object[])} )}
|
||||
*/
|
||||
@Deprecated
|
||||
long queryForLong(String sql, Object... args) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -748,7 +759,9 @@ public interface JdbcOperations {
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see #queryForInt(String)
|
||||
* @see java.sql.Types
|
||||
* @deprecated in favor of {@link #queryForObject(String, Object[], int[], Class)} )}
|
||||
*/
|
||||
@Deprecated
|
||||
int queryForInt(String sql, Object[] args, int[] argTypes) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -766,7 +779,9 @@ public interface JdbcOperations {
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws DataAccessException if the query fails
|
||||
* @see #queryForInt(String)
|
||||
* @deprecated in favor of {@link #queryForObject(String, Class, Object[])} )}
|
||||
*/
|
||||
@Deprecated
|
||||
int queryForInt(String sql, Object... args) throws DataAccessException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -477,11 +477,13 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
|
||||
return queryForObject(sql, getSingleColumnRowMapper(requiredType));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public long queryForLong(String sql) throws DataAccessException {
|
||||
Number number = queryForObject(sql, Long.class);
|
||||
return (number != null ? number.longValue() : 0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int queryForInt(String sql) throws DataAccessException {
|
||||
Number number = queryForObject(sql, Integer.class);
|
||||
return (number != null ? number.intValue() : 0);
|
||||
@@ -757,21 +759,25 @@ public class JdbcTemplate extends JdbcAccessor implements JdbcOperations {
|
||||
return queryForObject(sql, args, getColumnMapRowMapper());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public long queryForLong(String sql, Object[] args, int[] argTypes) throws DataAccessException {
|
||||
Number number = queryForObject(sql, args, argTypes, Long.class);
|
||||
return (number != null ? number.longValue() : 0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public long queryForLong(String sql, Object... args) throws DataAccessException {
|
||||
Number number = queryForObject(sql, args, Long.class);
|
||||
return (number != null ? number.longValue() : 0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int queryForInt(String sql, Object[] args, int[] argTypes) throws DataAccessException {
|
||||
Number number = queryForObject(sql, args, argTypes, Integer.class);
|
||||
return (number != null ? number.intValue() : 0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int queryForInt(String sql, Object... args) throws DataAccessException {
|
||||
Number number = queryForObject(sql, args, Integer.class);
|
||||
return (number != null ? number.intValue() : 0);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -56,33 +56,33 @@ public interface CallMetaDataProvider {
|
||||
|
||||
/**
|
||||
* Provide any modification of the procedure name passed in to match the meta data currently used.
|
||||
* This could include alterig the case.
|
||||
* This could include altering the case.
|
||||
*/
|
||||
String procedureNameToUse(String procedureName);
|
||||
|
||||
/**
|
||||
* Provide any modification of the catalog name passed in to match the meta data currently used.
|
||||
* This could include alterig the case.
|
||||
* This could include altering the case.
|
||||
*/
|
||||
String catalogNameToUse(String catalogName);
|
||||
|
||||
/**
|
||||
* Provide any modification of the schema name passed in to match the meta data currently used.
|
||||
* This could include alterig the case.
|
||||
* This could include altering the case.
|
||||
*/
|
||||
String schemaNameToUse(String schemaName);
|
||||
|
||||
/**
|
||||
* Provide any modification of the catalog name passed in to match the meta data currently used.
|
||||
* The reyurned value will be used for meta data lookups. This could include alterig the case used
|
||||
* or providing a base catalog if mone provided.
|
||||
* The returned value will be used for meta data lookups. This could include altering the case used
|
||||
* or providing a base catalog if none is provided.
|
||||
*/
|
||||
String metaDataCatalogNameToUse(String catalogName) ;
|
||||
|
||||
/**
|
||||
* Provide any modification of the schema name passed in to match the meta data currently used.
|
||||
* The reyurned value will be used for meta data lookups. This could include alterig the case used
|
||||
* or providing a base schema if mone provided.
|
||||
* The returned value will be used for meta data lookups. This could include altering the case used
|
||||
* or providing a base schema if none is provided.
|
||||
*/
|
||||
String metaDataSchemaNameToUse(String schemaName) ;
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -76,8 +76,8 @@ public interface TableMetaDataProvider {
|
||||
|
||||
/**
|
||||
* Provide any modification of the catalog name passed in to match the meta data currently used.
|
||||
* The reyurned value will be used for meta data lookups. This could include alterig the case used or
|
||||
* providing a base catalog if mone provided.
|
||||
* The returned value will be used for meta data lookups. This could include altering the case used or
|
||||
* providing a base catalog if none is provided.
|
||||
*
|
||||
* @param catalogName
|
||||
* @return catalog name to use
|
||||
@@ -86,8 +86,8 @@ public interface TableMetaDataProvider {
|
||||
|
||||
/**
|
||||
* Provide any modification of the schema name passed in to match the meta data currently used.
|
||||
* The reyurned value will be used for meta data lookups. This could include alterig the case used or
|
||||
* providing a base schema if mone provided.
|
||||
* The returned value will be used for meta data lookups. This could include altering the case used or
|
||||
* providing a base schema if none is provided.
|
||||
*
|
||||
* @param schemaName
|
||||
* @return schema name to use
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.jdbc.core.namedparam;
|
||||
|
||||
/**
|
||||
* A simple empty implementation of the {@link SqlParameterSource} interface.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @since 3.2.2
|
||||
*/
|
||||
public class EmptySqlParameterSource implements SqlParameterSource {
|
||||
|
||||
/**
|
||||
* A shared instance of {@link EmptySqlParameterSource}.
|
||||
*/
|
||||
public static final EmptySqlParameterSource INSTANCE = new EmptySqlParameterSource();
|
||||
|
||||
|
||||
public boolean hasValue(String paramName) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Object getValue(String paramName) throws IllegalArgumentException {
|
||||
throw new IllegalArgumentException("This SqlParameterSource is empty");
|
||||
}
|
||||
|
||||
public int getSqlType(String paramName) {
|
||||
return TYPE_UNKNOWN;
|
||||
}
|
||||
|
||||
public String getTypeName(String paramName) {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -88,6 +88,21 @@ public interface NamedParameterJdbcOperations {
|
||||
<T> T execute(String sql, Map<String, ?> paramMap, PreparedStatementCallback<T> action)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Execute a JDBC data access operation, implemented as callback action
|
||||
* working on a JDBC PreparedStatement. This allows for implementing arbitrary
|
||||
* data access operations on a single Statement, within Spring's managed
|
||||
* JDBC environment: that is, participating in Spring-managed transactions
|
||||
* and converting JDBC SQLExceptions into Spring's DataAccessException hierarchy.
|
||||
* <p>The callback action can return a result object, for example a
|
||||
* domain object or a collection of domain objects.
|
||||
* @param sql SQL to execute
|
||||
* @param action callback object that specifies the action
|
||||
* @return a result object returned by the action, or {@code null}
|
||||
* @throws DataAccessException if there is any problem
|
||||
*/
|
||||
<T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Query given SQL to create a prepared statement from SQL and a list
|
||||
* of arguments to bind to the query, reading the ResultSet with a
|
||||
@@ -115,6 +130,19 @@ public interface NamedParameterJdbcOperations {
|
||||
<T> T query(String sql, Map<String, ?> paramMap, ResultSetExtractor<T> rse)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Query given SQL to create a prepared statement from SQL,
|
||||
* reading the ResultSet with a ResultSetExtractor.
|
||||
* <p>Note: In contrast to the JdbcOperations method with the same signature,
|
||||
* this query variant always uses a PreparedStatement. It is effectively
|
||||
* equivalent to a query call with an empty parameter Map.
|
||||
* @param sql SQL query to execute
|
||||
* @param rse object that will extract results
|
||||
* @return an arbitrary result object, as returned by the ResultSetExtractor
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
*/
|
||||
<T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Query given SQL to create a prepared statement from SQL and a list of
|
||||
* arguments to bind to the query, reading the ResultSet on a per-row basis
|
||||
@@ -139,6 +167,18 @@ public interface NamedParameterJdbcOperations {
|
||||
*/
|
||||
void query(String sql, Map<String, ?> paramMap, RowCallbackHandler rch) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Query given SQL to create a prepared statement from SQL,
|
||||
* reading the ResultSet on a per-row basis with a RowCallbackHandler.
|
||||
* <p>Note: In contrast to the JdbcOperations method with the same signature,
|
||||
* this query variant always uses a PreparedStatement. It is effectively
|
||||
* equivalent to a query call with an empty parameter Map.
|
||||
* @param sql SQL query to execute
|
||||
* @param rch object that will extract results, one row at a time
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
*/
|
||||
void query(String sql, RowCallbackHandler rch) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Query given SQL to create a prepared statement from SQL and a list
|
||||
* of arguments to bind to the query, mapping each row to a Java object
|
||||
@@ -166,6 +206,19 @@ public interface NamedParameterJdbcOperations {
|
||||
<T> List<T> query(String sql, Map<String, ?> paramMap, RowMapper<T> rowMapper)
|
||||
throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Query given SQL to create a prepared statement from SQL,
|
||||
* mapping each row to a Java object via a RowMapper.
|
||||
* <p>Note: In contrast to the JdbcOperations method with the same signature,
|
||||
* this query variant always uses a PreparedStatement. It is effectively
|
||||
* equivalent to a query call with an empty parameter Map.
|
||||
* @param sql SQL query to execute
|
||||
* @param rowMapper object that will map one object per row
|
||||
* @return the result List, containing mapped objects
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
*/
|
||||
<T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException;
|
||||
|
||||
/**
|
||||
* Query given SQL to create a prepared statement from SQL and a list
|
||||
* of arguments to bind to the query, mapping a single result row to a
|
||||
@@ -245,8 +298,7 @@ public interface NamedParameterJdbcOperations {
|
||||
* @param paramSource container of arguments to bind to the query
|
||||
* @return the result Map (one entry for each column, using the column name as the key)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row, or does not return exactly
|
||||
* one column in that row
|
||||
* if the query does not return exactly one row
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate#queryForMap(String)
|
||||
* @see org.springframework.jdbc.core.ColumnMapRowMapper
|
||||
@@ -266,8 +318,7 @@ public interface NamedParameterJdbcOperations {
|
||||
* (leaving it to the PreparedStatement to guess the corresponding SQL type)
|
||||
* @return the result Map (one entry for each column, using the column name as the key)
|
||||
* @throws org.springframework.dao.IncorrectResultSizeDataAccessException
|
||||
* if the query does not return exactly one row, or does not return exactly
|
||||
* one column in that row
|
||||
* if the query does not return exactly one row
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate#queryForMap(String)
|
||||
* @see org.springframework.jdbc.core.ColumnMapRowMapper
|
||||
@@ -287,7 +338,9 @@ public interface NamedParameterJdbcOperations {
|
||||
* one column in that row
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate#queryForLong(String)
|
||||
* @deprecated in favor of {@link #queryForObject(String, SqlParameterSource, Class)}
|
||||
*/
|
||||
@Deprecated
|
||||
long queryForLong(String sql, SqlParameterSource paramSource) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -304,7 +357,9 @@ public interface NamedParameterJdbcOperations {
|
||||
* one column in that row
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate#queryForLong(String)
|
||||
* @deprecated in favor of {@link #queryForObject(String, Map, Class)}
|
||||
*/
|
||||
@Deprecated
|
||||
long queryForLong(String sql, Map<String, ?> paramMap) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -319,7 +374,9 @@ public interface NamedParameterJdbcOperations {
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate#queryForInt(String)
|
||||
* @deprecated in favor of {@link #queryForObject(String, SqlParameterSource, Class)}
|
||||
*/
|
||||
@Deprecated
|
||||
int queryForInt(String sql, SqlParameterSource paramSource) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -335,7 +392,9 @@ public interface NamedParameterJdbcOperations {
|
||||
* exactly one row, or does not return exactly one column in that row
|
||||
* @throws org.springframework.dao.DataAccessException if the query fails
|
||||
* @see org.springframework.jdbc.core.JdbcTemplate#queryForInt(String)
|
||||
* @deprecated in favor of {@link #queryForObject(String, Map, Class)}
|
||||
*/
|
||||
@Deprecated
|
||||
int queryForInt(String sql, Map<String, ?> paramMap) throws DataAccessException;
|
||||
|
||||
/**
|
||||
@@ -378,8 +437,8 @@ public interface NamedParameterJdbcOperations {
|
||||
* list of arguments to bind to the query, expecting a result list.
|
||||
* <p>The results will be mapped to a List (one entry for each row) of
|
||||
* Maps (one entry for each column, using the column name as the key).
|
||||
* Thus Each element in the list will be of the form returned by this interface's
|
||||
* queryForMap() methods.
|
||||
* Each element in the list will be of the form returned by this interface's
|
||||
* {@code queryForMap} methods.
|
||||
* @param sql SQL query to execute
|
||||
* @param paramSource container of arguments to bind to the query
|
||||
* @return a List that contains a Map per row
|
||||
@@ -394,7 +453,7 @@ public interface NamedParameterJdbcOperations {
|
||||
* <p>The results will be mapped to a List (one entry for each row) of
|
||||
* Maps (one entry for each column, using the column name as the key).
|
||||
* Each element in the list will be of the form returned by this interface's
|
||||
* queryForMap() methods.
|
||||
* {@code queryForMap} methods.
|
||||
* @param sql SQL query to execute
|
||||
* @param paramMap map of parameters to bind to the query
|
||||
* (leaving it to the PreparedStatement to guess the corresponding SQL type)
|
||||
@@ -499,7 +558,7 @@ public interface NamedParameterJdbcOperations {
|
||||
* @param batchValues the array of Maps containing the batch of arguments for the query
|
||||
* @return an array containing the numbers of rows affected by each update in the batch
|
||||
*/
|
||||
public int[] batchUpdate(String sql, Map<String, ?>[] batchValues);
|
||||
int[] batchUpdate(String sql, Map<String, ?>[] batchValues);
|
||||
|
||||
/**
|
||||
* Execute a batch using the supplied SQL statement with the batch of supplied arguments.
|
||||
@@ -507,6 +566,6 @@ public interface NamedParameterJdbcOperations {
|
||||
* @param batchArgs the array of {@link SqlParameterSource} containing the batch of arguments for the query
|
||||
* @return an array containing the numbers of rows affected by each update in the batch
|
||||
*/
|
||||
public int[] batchUpdate(String sql, SqlParameterSource[] batchArgs);
|
||||
int[] batchUpdate(String sql, SqlParameterSource[] batchArgs);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -137,6 +137,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
|
||||
return execute(sql, new MapSqlParameterSource(paramMap), action);
|
||||
}
|
||||
|
||||
public <T> T execute(String sql, PreparedStatementCallback<T> action) throws DataAccessException {
|
||||
return execute(sql, EmptySqlParameterSource.INSTANCE, action);
|
||||
}
|
||||
|
||||
public <T> T query(String sql, SqlParameterSource paramSource, ResultSetExtractor<T> rse)
|
||||
throws DataAccessException {
|
||||
|
||||
@@ -149,6 +153,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
|
||||
return query(sql, new MapSqlParameterSource(paramMap), rse);
|
||||
}
|
||||
|
||||
public <T> T query(String sql, ResultSetExtractor<T> rse) throws DataAccessException {
|
||||
return query(sql, EmptySqlParameterSource.INSTANCE, rse);
|
||||
}
|
||||
|
||||
public void query(String sql, SqlParameterSource paramSource, RowCallbackHandler rch)
|
||||
throws DataAccessException {
|
||||
|
||||
@@ -161,6 +169,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
|
||||
query(sql, new MapSqlParameterSource(paramMap), rch);
|
||||
}
|
||||
|
||||
public void query(String sql, RowCallbackHandler rch) throws DataAccessException {
|
||||
query(sql, EmptySqlParameterSource.INSTANCE, rch);
|
||||
}
|
||||
|
||||
public <T> List<T> query(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
|
||||
throws DataAccessException {
|
||||
|
||||
@@ -173,6 +185,10 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
|
||||
return query(sql, new MapSqlParameterSource(paramMap), rowMapper);
|
||||
}
|
||||
|
||||
public <T> List<T> query(String sql, RowMapper<T> rowMapper) throws DataAccessException {
|
||||
return query(sql, EmptySqlParameterSource.INSTANCE, rowMapper);
|
||||
}
|
||||
|
||||
public <T> T queryForObject(String sql, SqlParameterSource paramSource, RowMapper<T> rowMapper)
|
||||
throws DataAccessException {
|
||||
|
||||
@@ -206,20 +222,24 @@ public class NamedParameterJdbcTemplate implements NamedParameterJdbcOperations
|
||||
return queryForObject(sql, paramMap, new ColumnMapRowMapper());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public long queryForLong(String sql, SqlParameterSource paramSource) throws DataAccessException {
|
||||
Number number = queryForObject(sql, paramSource, Long.class);
|
||||
return (number != null ? number.longValue() : 0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public long queryForLong(String sql, Map<String, ?> paramMap) throws DataAccessException {
|
||||
return queryForLong(sql, new MapSqlParameterSource(paramMap));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int queryForInt(String sql, SqlParameterSource paramSource) throws DataAccessException {
|
||||
Number number = queryForObject(sql, paramSource, Integer.class);
|
||||
return (number != null ? number.intValue() : 0);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public int queryForInt(String sql, Map<String, ?> paramMap) throws DataAccessException {
|
||||
return queryForInt(sql, new MapSqlParameterSource(paramMap));
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user