Commit 28270ba2 authored by Emmanuel Bourg's avatar Emmanuel Bourg

New upstream version 4.3.19

parent ef9a891c
......@@ -52,7 +52,7 @@ configure(allprojects) { project ->
ext.hsqldbVersion = "2.3.4"
ext.httpasyncVersion = "4.1.3"
ext.httpclientVersion = "4.5.5"
ext.jackson2Version = "2.8.11.1"
ext.jackson2Version = "2.8.11.2"
ext.jasperreportsVersion = "6.2.1" // our tests fail with JR-internal NPEs against 6.2.2 and higher
ext.javamailVersion = "1.5.6"
ext.jettyVersion = "9.3.14.v20161028" // as of 9.3.15, Jetty has hard Servlet 3.1 requirement
......@@ -62,20 +62,20 @@ configure(allprojects) { project ->
ext.jtaVersion = "1.2"
ext.junitVersion = "4.12"
ext.log4jVersion = "1.2.17"
ext.nettyVersion = "4.1.25.Final"
ext.nettyVersion = "4.1.29.Final"
ext.okhttpVersion = "2.7.5"
ext.okhttp3Version = "3.8.1"
ext.openjpaVersion = "2.4.2"
ext.poiVersion = "3.14"
ext.reactorVersion = "2.0.8.RELEASE"
ext.romeVersion = "1.7.4"
ext.slf4jVersion = "1.7.21"
ext.slf4jVersion = "1.7.25"
ext.snakeyamlVersion = "1.17"
ext.snifferVersion = "1.16"
ext.testngVersion = "6.9.10"
ext.tiles2Version = "2.2.2"
ext.tiles3Version = "3.0.7"
ext.tomcatVersion = "8.5.31"
ext.tomcatVersion = "8.5.33"
ext.tyrusVersion = "1.3.5" // constrained by WebLogic 12.1.3 support
ext.undertowVersion = "1.3.33.Final"
ext.xmlunitVersion = "1.6"
......@@ -726,7 +726,7 @@ project("spring-web") {
}
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-joda:2.8.11")
testCompile("com.fasterxml.jackson.datatype:jackson-datatype-jdk8:2.8.11")
testCompile("com.fasterxml.jackson.module:jackson-module-kotlin:${jackson2Version}")
testCompile("com.fasterxml.jackson.module:jackson-module-kotlin:2.8.11.1")
testCompile("com.squareup.okhttp3:mockwebserver:${okhttp3Version}")
testRuntime("com.sun.mail:javax.mail:${javamailVersion}")
}
......
version=4.3.18.RELEASE
version=4.3.19.RELEASE
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -48,10 +48,11 @@ import java.lang.reflect.Method;
public interface MethodMatcher {
/**
* Perform static checking whether the given method matches. If this
* returns {@code false} or if the {@link #isRuntime()} method
* returns {@code false}, no runtime check (i.e. no.
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call) will be made.
* Perform static checking whether the given method matches.
* <p>If this returns {@code false} or if the {@link #isRuntime()}
* method returns {@code false}, no runtime check (i.e. no
* {@link #matches(java.lang.reflect.Method, Class, Object[])} call)
* will be made.
* @param method the candidate method
* @param targetClass the target class (may be {@code null}, in which case
* the candidate class must be taken to be the method's declaring class)
......
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -59,6 +59,9 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
private static final String AJC_MAGIC = "ajc$";
private static final Class<?>[] ASPECTJ_ANNOTATION_CLASSES = new Class<?>[] {
Pointcut.class, Around.class, Before.class, After.class, AfterReturning.class, AfterThrowing.class};
/** Logger available to subclasses */
protected final Log logger = LogFactory.getLog(getClass());
......@@ -122,14 +125,12 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
/**
* Find and return the first AspectJ annotation on the given method
* (there <i>should</i> only be one anyway...)
* (there <i>should</i> only be one anyway...).
*/
@SuppressWarnings("unchecked")
protected static AspectJAnnotation<?> findAspectJAnnotationOnMethod(Method method) {
Class<?>[] classesToLookFor = new Class<?>[] {
Before.class, Around.class, After.class, AfterReturning.class, AfterThrowing.class, Pointcut.class};
for (Class<?> c : classesToLookFor) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) c);
for (Class<?> clazz : ASPECTJ_ANNOTATION_CLASSES) {
AspectJAnnotation<?> foundAnnotation = findAnnotation(method, (Class<Annotation>) clazz);
if (foundAnnotation != null) {
return foundAnnotation;
}
......@@ -148,14 +149,13 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
}
/**
* Enum for AspectJ annotation types.
* @see AspectJAnnotation#getAnnotationType()
*/
protected enum AspectJAnnotationType {
AtPointcut,
AtBefore,
AtAfter,
AtAfterReturning,
AtAfterThrowing,
AtAround
AtPointcut, AtAround, AtBefore, AtAfter, AtAfterReturning, AtAfterThrowing
}
......@@ -165,18 +165,18 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
*/
protected static class AspectJAnnotation<A extends Annotation> {
private static final String[] EXPRESSION_PROPERTIES = new String[] {"value", "pointcut"};
private static final String[] EXPRESSION_ATTRIBUTES = new String[] {"pointcut", "value"};
private static Map<Class<?>, AspectJAnnotationType> annotationTypes =
new HashMap<Class<?>, AspectJAnnotationType>();
private static Map<Class<?>, AspectJAnnotationType> annotationTypeMap =
new HashMap<Class<?>, AspectJAnnotationType>(8);
static {
annotationTypes.put(Pointcut.class,AspectJAnnotationType.AtPointcut);
annotationTypes.put(After.class,AspectJAnnotationType.AtAfter);
annotationTypes.put(AfterReturning.class,AspectJAnnotationType.AtAfterReturning);
annotationTypes.put(AfterThrowing.class,AspectJAnnotationType.AtAfterThrowing);
annotationTypes.put(Around.class,AspectJAnnotationType.AtAround);
annotationTypes.put(Before.class,AspectJAnnotationType.AtBefore);
annotationTypeMap.put(Pointcut.class, AspectJAnnotationType.AtPointcut);
annotationTypeMap.put(Around.class, AspectJAnnotationType.AtAround);
annotationTypeMap.put(Before.class, AspectJAnnotationType.AtBefore);
annotationTypeMap.put(After.class, AspectJAnnotationType.AtAfter);
annotationTypeMap.put(AfterReturning.class, AspectJAnnotationType.AtAfterReturning);
annotationTypeMap.put(AfterThrowing.class, AspectJAnnotationType.AtAfterThrowing);
}
private final A annotation;
......@@ -190,44 +190,31 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
public AspectJAnnotation(A annotation) {
this.annotation = annotation;
this.annotationType = determineAnnotationType(annotation);
// We know these methods exist with the same name on each object,
// but need to invoke them reflectively as there isn't a common interface.
try {
this.pointcutExpression = resolveExpression(annotation);
this.argumentNames = (String) annotation.getClass().getMethod("argNames").invoke(annotation);
this.argumentNames = (String) AnnotationUtils.getValue(annotation, "argNames");
}
catch (Exception ex) {
throw new IllegalArgumentException(annotation + " cannot be an AspectJ annotation", ex);
throw new IllegalArgumentException(annotation + " is not a valid AspectJ annotation", ex);
}
}
private AspectJAnnotationType determineAnnotationType(A annotation) {
for (Class<?> type : annotationTypes.keySet()) {
if (type.isInstance(annotation)) {
return annotationTypes.get(type);
}
AspectJAnnotationType type = annotationTypeMap.get(annotation.annotationType());
if (type != null) {
return type;
}
throw new IllegalStateException("Unknown annotation type: " + annotation.toString());
throw new IllegalStateException("Unknown annotation type: " + annotation);
}
private String resolveExpression(A annotation) throws Exception {
String expression = null;
for (String methodName : EXPRESSION_PROPERTIES) {
Method method;
try {
method = annotation.getClass().getDeclaredMethod(methodName);
}
catch (NoSuchMethodException ex) {
method = null;
}
if (method != null) {
String candidate = (String) method.invoke(annotation);
if (StringUtils.hasText(candidate)) {
expression = candidate;
}
private String resolveExpression(A annotation) {
for (String attributeName : EXPRESSION_ATTRIBUTES) {
String candidate = (String) AnnotationUtils.getValue(annotation, attributeName);
if (StringUtils.hasText(candidate)) {
return candidate;
}
}
return expression;
throw new IllegalStateException("Failed to resolve expression: " + annotation);
}
public AspectJAnnotationType getAnnotationType() {
......@@ -268,11 +255,11 @@ public abstract class AbstractAspectJAdvisorFactory implements AspectJAdvisorFac
if (annotation == null) {
return null;
}
StringTokenizer strTok = new StringTokenizer(annotation.getArgumentNames(), ",");
if (strTok.countTokens() > 0) {
String[] names = new String[strTok.countTokens()];
StringTokenizer nameTokens = new StringTokenizer(annotation.getArgumentNames(), ",");
if (nameTokens.countTokens() > 0) {
String[] names = new String[nameTokens.countTokens()];
for (int i = 0; i < names.length; i++) {
names[i] = strTok.nextToken();
names[i] = nameTokens.nextToken();
}
return names;
}
......
/*
* Copyright 2002-2015 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -109,29 +109,22 @@ class InstantiationModelAwarePointcutAdvisorImpl
/**
* The pointcut for Spring AOP to use. Actual behaviour of the pointcut will change
* depending on the state of the advice.
* The pointcut for Spring AOP to use.
* Actual behaviour of the pointcut will change depending on the state of the advice.
*/
@Override
public Pointcut getPointcut() {
return this.pointcut;
}
/**
* This is only of interest for Spring AOP: AspectJ instantiation semantics
* are much richer. In AspectJ terminology, all a return of {@code true}
* means here is that the aspect is not a SINGLETON.
*/
@Override
public boolean isPerInstance() {
return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON);
public boolean isLazy() {
return this.lazy;
}
/**
* Return the AspectJ AspectMetadata for this advisor.
*/
public AspectMetadata getAspectMetadata() {
return this.aspectInstanceFactory.getAspectMetadata();
@Override
public synchronized boolean isAdviceInstantiated() {
return (this.instantiatedAdvice != null);
}
/**
......@@ -145,20 +138,26 @@ class InstantiationModelAwarePointcutAdvisorImpl
return this.instantiatedAdvice;
}
@Override
public boolean isLazy() {
return this.lazy;
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
}
/**
* This is only of interest for Spring AOP: AspectJ instantiation semantics
* are much richer. In AspectJ terminology, all a return of {@code true}
* means here is that the aspect is not a SINGLETON.
*/
@Override
public synchronized boolean isAdviceInstantiated() {
return (this.instantiatedAdvice != null);
public boolean isPerInstance() {
return (getAspectMetadata().getAjType().getPerClause().getKind() != PerClauseKind.SINGLETON);
}
private Advice instantiateAdvice(AspectJExpressionPointcut pcut) {
return this.aspectJAdvisorFactory.getAdvice(this.aspectJAdviceMethod, pcut,
this.aspectInstanceFactory, this.declarationOrder, this.aspectName);
/**
* Return the AspectJ AspectMetadata for this advisor.
*/
public AspectMetadata getAspectMetadata() {
return this.aspectInstanceFactory.getAspectMetadata();
}
public MetadataAwareAspectInstanceFactory getAspectInstanceFactory() {
......@@ -213,33 +212,26 @@ class InstantiationModelAwarePointcutAdvisorImpl
}
else {
switch (aspectJAnnotation.getAnnotationType()) {
case AtAfter:
case AtAfterReturning:
case AtAfterThrowing:
this.isAfterAdvice = true;
this.isBeforeAdvice = false;
break;
case AtAround:
case AtPointcut:
this.isAfterAdvice = false;
case AtAround:
this.isBeforeAdvice = false;
this.isAfterAdvice = false;
break;
case AtBefore:
this.isAfterAdvice = false;
this.isBeforeAdvice = true;
this.isAfterAdvice = false;
break;
case AtAfter:
case AtAfterReturning:
case AtAfterThrowing:
this.isBeforeAdvice = false;
this.isAfterAdvice = true;
break;
}
}
}
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
private void readObject(ObjectInputStream inputStream) throws IOException, ClassNotFoundException {
inputStream.defaultReadObject();
try {
......@@ -250,11 +242,18 @@ class InstantiationModelAwarePointcutAdvisorImpl
}
}
@Override
public String toString() {
return "InstantiationModelAwarePointcutAdvisor: expression [" + getDeclaredPointcut().getExpression() +
"]; advice method [" + this.aspectJAdviceMethod + "]; perClauseKind=" +
this.aspectInstanceFactory.getAspectMetadata().getAjType().getPerClause().getKind();
}
/**
* Pointcut implementation that changes its behaviour when the advice is instantiated.
* Note that this is a <i>dynamic</i> pointcut. Otherwise it might
* be optimized out if it does not at first match statically.
* Note that this is a <i>dynamic</i> pointcut; otherwise it might be optimized out
* if it does not at first match statically.
*/
private class PerTargetInstantiationModelPointcut extends DynamicMethodMatcherPointcut {
......@@ -264,8 +263,9 @@ class InstantiationModelAwarePointcutAdvisorImpl
private LazySingletonAspectInstanceFactoryDecorator aspectInstanceFactory;
private PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
public PerTargetInstantiationModelPointcut(AspectJExpressionPointcut declaredPointcut,
Pointcut preInstantiationPointcut, MetadataAwareAspectInstanceFactory aspectInstanceFactory) {
this.declaredPointcut = declaredPointcut;
this.preInstantiationPointcut = preInstantiationPointcut;
if (aspectInstanceFactory instanceof LazySingletonAspectInstanceFactoryDecorator) {
......@@ -275,7 +275,8 @@ class InstantiationModelAwarePointcutAdvisorImpl
@Override
public boolean matches(Method method, Class<?> targetClass) {
// We're either instantiated and matching on declared pointcut, or uninstantiated matching on either pointcut
// We're either instantiated and matching on declared pointcut,
// or uninstantiated matching on either pointcut...
return (isAspectMaterialized() && this.declaredPointcut.matches(method, targetClass)) ||
this.preInstantiationPointcut.getMethodMatcher().matches(method, targetClass);
}
......
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author 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,9 +20,9 @@ import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedList;
import java.util.List;
import org.aopalliance.aop.Advice;
......@@ -131,7 +131,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
MetadataAwareAspectInstanceFactory lazySingletonAspectInstanceFactory =
new LazySingletonAspectInstanceFactoryDecorator(aspectInstanceFactory);
List<Advisor> advisors = new LinkedList<Advisor>();
List<Advisor> advisors = new ArrayList<Advisor>();
for (Method method : getAdvisorMethods(aspectClass)) {
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, advisors.size(), aspectName);
if (advisor != null) {
......@@ -157,7 +157,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
}
private List<Method> getAdvisorMethods(Class<?> aspectClass) {
final List<Method> methods = new LinkedList<Method>();
final List<Method> methods = new ArrayList<Method>();
ReflectionUtils.doWithMethods(aspectClass, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException {
......@@ -176,7 +176,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
* for the given introduction field.
* <p>Resulting Advisors will need to be evaluated for targets.
* @param introductionField the field to introspect
* @return {@code null} if not an Advisor
* @return the Advisor instance, or {@code null} if not an Advisor
*/
private Advisor getDeclareParentsAdvisor(Field introductionField) {
DeclareParents declareParents = introductionField.getAnnotation(DeclareParents.class);
......@@ -253,6 +253,15 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
AbstractAspectJAdvice springAdvice;
switch (aspectJAnnotation.getAnnotationType()) {
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtBefore:
springAdvice = new AspectJMethodBeforeAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
......@@ -277,15 +286,6 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
springAdvice.setThrowingName(afterThrowingAnnotation.throwing());
}
break;
case AtAround:
springAdvice = new AspectJAroundAdvice(
candidateAdviceMethod, expressionPointcut, aspectInstanceFactory);
break;
case AtPointcut:
if (logger.isDebugEnabled()) {
logger.debug("Processing pointcut '" + candidateAdviceMethod.getName() + "'");
}
return null;
default:
throw new UnsupportedOperationException(
"Unsupported advice type on method: " + candidateAdviceMethod);
......@@ -299,6 +299,7 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
springAdvice.setArgumentNamesFromStringArray(argNames);
}
springAdvice.calculateArgumentBindings();
return springAdvice;
}
......
/*
* Copyright 2002-2016 the original author or authors.
* Copyright 2002-2018 the original author 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,11 +31,10 @@ import org.springframework.util.Assert;
/**
* Utility class for handling registration of AOP auto-proxy creators.
*
* <p>Only a single auto-proxy creator can be registered yet multiple concrete
* implementations are available. Therefore this class wraps a simple escalation
* protocol, allowing classes to request a particular auto-proxy creator and know
* that class, {@code or a subclass thereof}, will eventually be resident
* in the application context.
* <p>Only a single auto-proxy creator should be registered yet multiple concrete
* implementations are available. This class provides a simple escalation protocol,
* allowing a caller to request a particular auto-proxy creator and know that creator,
* <i>or a more capable variant thereof</i>, will be registered as a post-processor.
*
* @author Rob Harrop
* @author Juergen Hoeller
......@@ -54,12 +53,10 @@ public abstract class AopConfigUtils {
/**
* Stores the auto proxy creator classes in escalation order.
*/
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<Class<?>>();
private static final List<Class<?>> APC_PRIORITY_LIST = new ArrayList<Class<?>>(3);
/**
* Setup the escalation list.
*/
static {
// Set up the escalation list...
APC_PRIORITY_LIST.add(InfrastructureAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AspectJAwareAdvisorAutoProxyCreator.class);
APC_PRIORITY_LIST.add(AnnotationAwareAspectJAutoProxyCreator.class);
......@@ -107,6 +104,7 @@ public abstract class AopConfigUtils {
private static BeanDefinition registerOrEscalateApcAsRequired(Class<?> cls, BeanDefinitionRegistry registry, Object source) {
Assert.notNull(registry, "BeanDefinitionRegistry must not be null");
if (registry.containsBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME)) {
BeanDefinition apcDefinition = registry.getBeanDefinition(AUTO_PROXY_CREATOR_BEAN_NAME);
if (!cls.getName().equals(apcDefinition.getBeanClassName())) {
......@@ -118,6 +116,7 @@ public abstract class AopConfigUtils {
}
return null;
}
RootBeanDefinition beanDefinition = new RootBeanDefinition(cls);
beanDefinition.setSource(source);
beanDefinition.getPropertyValues().add("order", Ordered.HIGHEST_PRECEDENCE);
......
/*
* Copyright 2002-2017 the original author or authors.
* Copyright 2002-2018 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
......@@ -27,11 +27,11 @@ import org.springframework.beans.factory.xml.ParserContext;
* Utility class for handling registration of auto-proxy creators used internally
* by the '{@code aop}' namespace tags.
*
* <p>Only a single auto-proxy creator can be registered and multiple tags may wish
* to register different concrete implementations. As such this class delegates to
* {@link AopConfigUtils} which wraps a simple escalation protocol. Therefore classes
* may request a particular auto-proxy creator and know that class, <i>or a subclass
* thereof</i>, will eventually be resident in the application context.
* <p>Only a single auto-proxy creator should be registered and multiple configuration
* elements may wish to register different concrete implementations. As such this class
* delegates to {@link AopConfigUtils} which provides a simple escalation protocol.
* Callers may request a particular auto-proxy creator and know that creator,
* <i>or a more capable variant thereof</i>, will be registered as a post-processor.
*
* @author Rob Harrop
* @author Juergen Hoeller
......@@ -94,9 +94,8 @@ public abstract class AopNamespaceUtils {
private static void registerComponentIfNecessary(BeanDefinition beanDefinition, ParserContext parserContext) {
if (beanDefinition != null) {
BeanComponentDefinition componentDefinition =
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME);
parserContext.registerComponent(componentDefinition);
parserContext.registerComponent(
new BeanComponentDefinition(beanDefinition, AopConfigUtils.AUTO_PROXY_CREATOR_BEAN_NAME));