mirror of
https://github.com/spring-projects/spring-framework
synced 2026-06-08 17:33:33 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f0088831a9 |
+3
-3
@@ -28,8 +28,8 @@ configure(allprojects) { project ->
|
||||
dependencyManagement {
|
||||
imports {
|
||||
mavenBom "com.fasterxml.jackson:jackson-bom:2.12.7"
|
||||
mavenBom "io.netty:netty-bom:4.1.111.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.45"
|
||||
mavenBom "io.netty:netty-bom:4.1.109.Final"
|
||||
mavenBom "io.projectreactor:reactor-bom:2020.0.44"
|
||||
mavenBom "io.r2dbc:r2dbc-bom:Arabba-SR13"
|
||||
mavenBom "io.rsocket:rsocket-bom:1.1.3"
|
||||
mavenBom "org.eclipse.jetty:jetty-bom:9.4.54.v20240208"
|
||||
@@ -362,7 +362,7 @@ configure([rootProject] + javaProjects) { project ->
|
||||
// JSR-305 only used for non-required meta-annotations
|
||||
compileOnly("com.google.code.findbugs:jsr305")
|
||||
testCompileOnly("com.google.code.findbugs:jsr305")
|
||||
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.42")
|
||||
checkstyle("io.spring.javaformat:spring-javaformat-checkstyle:0.0.41")
|
||||
}
|
||||
|
||||
ext.javadocLinks = [
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
version=5.3.37
|
||||
version=5.3.35
|
||||
org.gradle.jvmargs=-Xmx2048m
|
||||
org.gradle.caching=true
|
||||
org.gradle.parallel=true
|
||||
|
||||
+1
-1
@@ -63,7 +63,7 @@ class EnableCachingIntegrationTests {
|
||||
// attempt was made to look up the AJ aspect. It's due to classpath issues
|
||||
// in .integration-tests that it's not found.
|
||||
assertThatException().isThrownBy(ctx::refresh)
|
||||
.withMessageContaining("AspectJCachingConfiguration");
|
||||
.withMessageContaining("AspectJCachingConfiguration");
|
||||
}
|
||||
|
||||
|
||||
|
||||
Vendored
+2
-1
@@ -561,7 +561,8 @@ public class EnvironmentSystemIntegrationTests {
|
||||
{
|
||||
ConfigurableApplicationContext ctx = new AnnotationConfigApplicationContext();
|
||||
ctx.getEnvironment().setRequiredProperties("foo", "bar");
|
||||
assertThatExceptionOfType(MissingRequiredPropertiesException.class).isThrownBy(ctx::refresh);
|
||||
assertThatExceptionOfType(MissingRequiredPropertiesException.class).isThrownBy(
|
||||
ctx::refresh);
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
+1
-1
@@ -97,7 +97,7 @@ class EnableTransactionManagementIntegrationTests {
|
||||
ctx.register(Config.class, AspectJTxConfig.class);
|
||||
// this test is a bit fragile, but gets the job done, proving that an
|
||||
// attempt was made to look up the AJ aspect. It's due to classpath issues
|
||||
// in integration-tests that it's not found.
|
||||
// in .integration-tests that it's not found.
|
||||
assertThatException()
|
||||
.isThrownBy(ctx::refresh)
|
||||
.withMessageContaining("AspectJJtaTransactionManagementConfiguration");
|
||||
|
||||
+3
-33
@@ -18,7 +18,6 @@ package org.springframework.aop.aspectj;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Proxy;
|
||||
import java.util.Arrays;
|
||||
@@ -43,7 +42,6 @@ import org.aspectj.weaver.tools.PointcutParameter;
|
||||
import org.aspectj.weaver.tools.PointcutParser;
|
||||
import org.aspectj.weaver.tools.PointcutPrimitive;
|
||||
import org.aspectj.weaver.tools.ShadowMatch;
|
||||
import org.aspectj.weaver.tools.UnsupportedPointcutPrimitiveException;
|
||||
|
||||
import org.springframework.aop.ClassFilter;
|
||||
import org.springframework.aop.IntroductionAwareMethodMatcher;
|
||||
@@ -87,8 +85,6 @@ import org.springframework.util.StringUtils;
|
||||
public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
implements ClassFilter, IntroductionAwareMethodMatcher, BeanFactoryAware {
|
||||
|
||||
private static final String AJC_MAGIC = "ajc$";
|
||||
|
||||
private static final Set<PointcutPrimitive> SUPPORTED_PRIMITIVES = new HashSet<>();
|
||||
|
||||
static {
|
||||
@@ -110,8 +106,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
@Nullable
|
||||
private Class<?> pointcutDeclarationScope;
|
||||
|
||||
private boolean aspectCompiledByAjc;
|
||||
|
||||
private String[] pointcutParameterNames = new String[0];
|
||||
|
||||
private Class<?>[] pointcutParameterTypes = new Class<?>[0];
|
||||
@@ -125,8 +119,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
@Nullable
|
||||
private transient PointcutExpression pointcutExpression;
|
||||
|
||||
private transient boolean pointcutParsingFailed = false;
|
||||
|
||||
private transient Map<Method, ShadowMatch> shadowMatchCache = new ConcurrentHashMap<>(32);
|
||||
|
||||
|
||||
@@ -143,7 +135,7 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
* @param paramTypes the parameter types for the pointcut
|
||||
*/
|
||||
public AspectJExpressionPointcut(Class<?> declarationScope, String[] paramNames, Class<?>[] paramTypes) {
|
||||
setPointcutDeclarationScope(declarationScope);
|
||||
this.pointcutDeclarationScope = declarationScope;
|
||||
if (paramNames.length != paramTypes.length) {
|
||||
throw new IllegalStateException(
|
||||
"Number of pointcut parameter names must match number of pointcut parameter types");
|
||||
@@ -158,7 +150,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
*/
|
||||
public void setPointcutDeclarationScope(Class<?> pointcutDeclarationScope) {
|
||||
this.pointcutDeclarationScope = pointcutDeclarationScope;
|
||||
this.aspectCompiledByAjc = compiledByAjc(pointcutDeclarationScope);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,15 +274,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
|
||||
@Override
|
||||
public boolean matches(Class<?> targetClass) {
|
||||
if (this.pointcutParsingFailed) {
|
||||
// Pointcut parsing failed before below -> avoid trying again.
|
||||
return false;
|
||||
}
|
||||
if (this.aspectCompiledByAjc && compiledByAjc(targetClass)) {
|
||||
// ajc-compiled aspect class for ajc-compiled target class -> already weaved.
|
||||
return false;
|
||||
}
|
||||
|
||||
try {
|
||||
try {
|
||||
return obtainPointcutExpression().couldMatchJoinPointsInType(targetClass);
|
||||
@@ -305,11 +287,8 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalStateException | UnsupportedPointcutPrimitiveException ex) {
|
||||
this.pointcutParsingFailed = true;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Pointcut parser rejected expression [" + getExpression() + "]: " + ex);
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalStateException ex) {
|
||||
throw ex;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
logger.debug("PointcutExpression matching rejected target class", ex);
|
||||
@@ -543,15 +522,6 @@ public class AspectJExpressionPointcut extends AbstractExpressionPointcut
|
||||
return shadowMatch;
|
||||
}
|
||||
|
||||
private static boolean compiledByAjc(Class<?> clazz) {
|
||||
for (Field field : clazz.getDeclaredFields()) {
|
||||
if (field.getName().startsWith(AJC_MAGIC)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object other) {
|
||||
|
||||
+19
-31
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2020 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,12 +22,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.aspectj.lang.reflect.PerClauseKind;
|
||||
|
||||
import org.springframework.aop.Advisor;
|
||||
import org.springframework.aop.framework.AopConfigException;
|
||||
import org.springframework.beans.factory.BeanFactoryUtils;
|
||||
import org.springframework.beans.factory.ListableBeanFactory;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -43,8 +40,6 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(BeanFactoryAspectJAdvisorsBuilder.class);
|
||||
|
||||
private final ListableBeanFactory beanFactory;
|
||||
|
||||
private final AspectJAdvisorFactory advisorFactory;
|
||||
@@ -107,37 +102,30 @@ public class BeanFactoryAspectJAdvisorsBuilder {
|
||||
continue;
|
||||
}
|
||||
if (this.advisorFactory.isAspect(beanType)) {
|
||||
try {
|
||||
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
||||
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
||||
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
this.advisorsCache.put(beanName, classAdvisors);
|
||||
}
|
||||
else {
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
}
|
||||
advisors.addAll(classAdvisors);
|
||||
aspectNames.add(beanName);
|
||||
AspectMetadata amd = new AspectMetadata(beanType, beanName);
|
||||
if (amd.getAjType().getPerClause().getKind() == PerClauseKind.SINGLETON) {
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new BeanFactoryAspectInstanceFactory(this.beanFactory, beanName);
|
||||
List<Advisor> classAdvisors = this.advisorFactory.getAdvisors(factory);
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
this.advisorsCache.put(beanName, classAdvisors);
|
||||
}
|
||||
else {
|
||||
// Per target or per this.
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
throw new IllegalArgumentException("Bean with name '" + beanName +
|
||||
"' is a singleton, but aspect instantiation model is not singleton");
|
||||
}
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||
}
|
||||
aspectNames.add(beanName);
|
||||
advisors.addAll(classAdvisors);
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalStateException | AopConfigException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ignoring incompatible aspect [" + beanType.getName() + "]: " + ex);
|
||||
else {
|
||||
// Per target or per this.
|
||||
if (this.beanFactory.isSingleton(beanName)) {
|
||||
throw new IllegalArgumentException("Bean with name '" + beanName +
|
||||
"' is a singleton, but aspect instantiation model is not singleton");
|
||||
}
|
||||
MetadataAwareAspectInstanceFactory factory =
|
||||
new PrototypeAspectInstanceFactory(this.beanFactory, beanName);
|
||||
this.aspectFactoryCache.put(beanName, factory);
|
||||
advisors.addAll(this.advisorFactory.getAdvisors(factory));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+14
-25
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -50,7 +50,6 @@ import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.converter.ConvertingComparator;
|
||||
import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.ReflectionUtils.MethodFilter;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -134,19 +133,17 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
|
||||
List<Advisor> advisors = new ArrayList<>();
|
||||
for (Method method : getAdvisorMethods(aspectClass)) {
|
||||
if (method.equals(ClassUtils.getMostSpecificMethod(method, aspectClass))) {
|
||||
// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
|
||||
// to getAdvisor(...) to represent the "current position" in the declared methods list.
|
||||
// However, since Java 7 the "current position" is not valid since the JDK no longer
|
||||
// returns declared methods in the order in which they are declared in the source code.
|
||||
// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
|
||||
// discovered via reflection in order to support reliable advice ordering across JVM launches.
|
||||
// Specifically, a value of 0 aligns with the default value used in
|
||||
// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
|
||||
if (advisor != null) {
|
||||
advisors.add(advisor);
|
||||
}
|
||||
// Prior to Spring Framework 5.2.7, advisors.size() was supplied as the declarationOrderInAspect
|
||||
// to getAdvisor(...) to represent the "current position" in the declared methods list.
|
||||
// However, since Java 7 the "current position" is not valid since the JDK no longer
|
||||
// returns declared methods in the order in which they are declared in the source code.
|
||||
// Thus, we now hard code the declarationOrderInAspect to 0 for all advice methods
|
||||
// discovered via reflection in order to support reliable advice ordering across JVM launches.
|
||||
// Specifically, a value of 0 aligns with the default value used in
|
||||
// AspectJPrecedenceComparator.getAspectDeclarationOrder(Advisor).
|
||||
Advisor advisor = getAdvisor(method, lazySingletonAspectInstanceFactory, 0, aspectName);
|
||||
if (advisor != null) {
|
||||
advisors.add(advisor);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,16 +210,8 @@ public class ReflectiveAspectJAdvisorFactory extends AbstractAspectJAdvisorFacto
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
|
||||
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
|
||||
}
|
||||
catch (IllegalArgumentException | IllegalStateException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Ignoring incompatible advice method: " + candidateAdviceMethod, ex);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return new InstantiationModelAwarePointcutAdvisorImpl(expressionPointcut, candidateAdviceMethod,
|
||||
this, aspectInstanceFactory, declarationOrderInAspect, aspectName);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
||||
+2
-2
@@ -39,13 +39,13 @@ import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.beans.testfixture.beans.subpkg.DeepBean;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
/**
|
||||
* @author Rob Harrop
|
||||
* @author Rod Johnson
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AspectJExpressionPointcutTests {
|
||||
|
||||
@@ -244,7 +244,7 @@ public class AspectJExpressionPointcutTests {
|
||||
@Test
|
||||
public void testInvalidExpression() {
|
||||
String expression = "execution(void org.springframework.beans.testfixture.beans.TestBean.setSomeNumber(Number) && args(Double)";
|
||||
assertThat(getPointcut(expression).getClassFilter().matches(Object.class)).isFalse();
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> getPointcut(expression).getClassFilter().matches(Object.class));
|
||||
}
|
||||
|
||||
private TestBean getAdvisedProxy(String pointcutExpression, CallCountingInterceptor interceptor) {
|
||||
|
||||
+18
-48
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -37,6 +37,7 @@ import org.aspectj.lang.annotation.DeclareParents;
|
||||
import org.aspectj.lang.annotation.DeclarePrecedence;
|
||||
import org.aspectj.lang.annotation.Pointcut;
|
||||
import org.aspectj.lang.reflect.MethodSignature;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import test.aop.DefaultLockable;
|
||||
import test.aop.Lockable;
|
||||
@@ -75,24 +76,25 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
/**
|
||||
* To be overridden by concrete test subclasses.
|
||||
* @return the fixture
|
||||
*/
|
||||
protected abstract AspectJAdvisorFactory getFixture();
|
||||
|
||||
|
||||
@Test
|
||||
void rejectsPerCflowAspect() {
|
||||
assertThatExceptionOfType(AopConfigException.class)
|
||||
.isThrownBy(() -> getFixture().getAdvisors(
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowAspect(), "someBean")))
|
||||
.withMessageContaining("PERCFLOW");
|
||||
.withMessageContaining("PERCFLOW");
|
||||
}
|
||||
|
||||
@Test
|
||||
void rejectsPerCflowBelowAspect() {
|
||||
assertThatExceptionOfType(AopConfigException.class)
|
||||
.isThrownBy(() -> getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(), "someBean")))
|
||||
.withMessageContaining("PERCFLOWBELOW");
|
||||
assertThatExceptionOfType(AopConfigException.class).isThrownBy(() ->
|
||||
getFixture().getAdvisors(
|
||||
new SingletonMetadataAwareAspectInstanceFactory(new PerCflowBelowAspect(), "someBean")))
|
||||
.withMessageContaining("PERCFLOWBELOW");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -383,7 +385,8 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertThat(lockable.locked()).as("Already locked").isTrue();
|
||||
lockable.lock();
|
||||
assertThat(lockable.locked()).as("Real target ignores locking").isTrue();
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(lockable::unlock);
|
||||
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
|
||||
lockable.unlock());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -410,7 +413,9 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
lockable.locked();
|
||||
}
|
||||
|
||||
// TODO: Why does this test fail? It hasn't been run before, so it maybe never actually passed...
|
||||
@Test
|
||||
@Disabled
|
||||
void introductionWithArgumentBinding() {
|
||||
TestBean target = new TestBean();
|
||||
|
||||
@@ -518,16 +523,6 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
assertThat(aspect.invocations).containsExactly("around - start", "before", "after throwing", "after", "around - end");
|
||||
}
|
||||
|
||||
@Test
|
||||
void parentAspect() {
|
||||
TestBean target = new TestBean("Jane", 42);
|
||||
MetadataAwareAspectInstanceFactory aspectInstanceFactory = new SingletonMetadataAwareAspectInstanceFactory(
|
||||
new IncrementingAspect(), "incrementingAspect");
|
||||
ITestBean proxy = (ITestBean) createProxy(target,
|
||||
getFixture().getAdvisors(aspectInstanceFactory), ITestBean.class);
|
||||
assertThat(proxy.getAge()).isEqualTo(86); // (42 + 1) * 2
|
||||
}
|
||||
|
||||
@Test
|
||||
void failureWithoutExplicitDeclarePrecedence() {
|
||||
TestBean target = new TestBean();
|
||||
@@ -652,7 +647,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
static class NamedPointcutAspectWithFQN {
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private final ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
|
||||
private ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
|
||||
|
||||
@Pointcut("execution(* getAge())")
|
||||
void getAge() {
|
||||
@@ -772,31 +767,6 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
abstract static class DoublingAspect {
|
||||
|
||||
@Around("execution(* getAge())")
|
||||
public Object doubleAge(ProceedingJoinPoint pjp) throws Throwable {
|
||||
return ((int) pjp.proceed()) * 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
static class IncrementingAspect extends DoublingAspect {
|
||||
|
||||
@Override
|
||||
public Object doubleAge(ProceedingJoinPoint pjp) throws Throwable {
|
||||
return ((int) pjp.proceed()) * 2;
|
||||
}
|
||||
|
||||
@Around("execution(* getAge())")
|
||||
public int incrementAge(ProceedingJoinPoint pjp) throws Throwable {
|
||||
return ((int) pjp.proceed()) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Aspect
|
||||
private static class InvocationTrackingAspect {
|
||||
|
||||
@@ -854,7 +824,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Around("getAge()")
|
||||
int preventExecution(ProceedingJoinPoint pjp) {
|
||||
return 42;
|
||||
return 666;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -874,7 +844,7 @@ abstract class AbstractAspectJAdvisorFactoryTests {
|
||||
|
||||
@Around("getAge()")
|
||||
int preventExecution(ProceedingJoinPoint pjp) {
|
||||
return 42;
|
||||
return 666;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1096,7 +1066,7 @@ class PerThisAspect {
|
||||
|
||||
// Just to check that this doesn't cause problems with introduction processing
|
||||
@SuppressWarnings("unused")
|
||||
private final ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
|
||||
private ITestBean fieldThatShouldBeIgnoredBySpringAtAspectJProcessing = new TestBean();
|
||||
|
||||
@Around("execution(int *.getAge())")
|
||||
int returnCountAsAge() {
|
||||
|
||||
+2
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2015 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,12 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Adrian Colyer
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class AutoProxyWithCodeStyleAspectsTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
public void noAutoProxyingOfAjcCompiledAspects() {
|
||||
public void noAutoproxyingOfAjcCompiledAspects() {
|
||||
new ClassPathXmlApplicationContext("org/springframework/aop/aspectj/autoproxy/ajcAutoproxyTests.xml");
|
||||
}
|
||||
|
||||
|
||||
+1
-5
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2015 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,10 +20,6 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* @author Ramnivas Laddad
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class SpringConfiguredWithAutoProxyingTests {
|
||||
|
||||
@Test
|
||||
|
||||
+4
-17
@@ -2,29 +2,16 @@
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:aop="http://www.springframework.org/schema/aop"
|
||||
xmlns:cache="http://www.springframework.org/schema/cache"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans-2.0.xsd
|
||||
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-2.0.xsd
|
||||
http://www.springframework.org/schema/cache https://www.springframework.org/schema/cache/spring-cache-3.1.xsd
|
||||
http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context-2.5.xsd">
|
||||
http://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-2.0.xsd">
|
||||
|
||||
<aop:aspectj-autoproxy/>
|
||||
|
||||
<context:spring-configured/>
|
||||
|
||||
<cache:annotation-driven mode="aspectj"/>
|
||||
|
||||
<bean id="cacheManager" class="org.springframework.cache.support.NoOpCacheManager"/>
|
||||
|
||||
<bean id="myAspect" class="org.springframework.aop.aspectj.autoproxy.CodeStyleAspect" factory-method="aspectOf">
|
||||
<bean id="myAspect" class="org.springframework.aop.aspectj.autoproxy.CodeStyleAspect"
|
||||
factory-method="aspectOf">
|
||||
<property name="foo" value="bar"/>
|
||||
</bean>
|
||||
|
||||
<bean id="otherBean" class="org.springframework.beans.factory.aspectj.ShouldBeConfiguredBySpring"/>
|
||||
|
||||
<bean id="yetAnotherBean" class="org.springframework.beans.factory.aspectj.ShouldBeConfiguredBySpring"/>
|
||||
|
||||
<bean id="configuredBean" class="org.springframework.beans.factory.aspectj.ShouldBeConfiguredBySpring" lazy-init="true"/>
|
||||
<bean id="otherBean" class="java.lang.Object"/>
|
||||
|
||||
</beans>
|
||||
|
||||
Vendored
+2
-1
@@ -24,7 +24,8 @@
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="defaultCache" class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
|
||||
<bean id="defaultCache"
|
||||
class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean">
|
||||
<property name="name" value="default"/>
|
||||
</bean>
|
||||
|
||||
|
||||
+4
-2
@@ -7,10 +7,12 @@
|
||||
http://www.springframework.org/schema/task
|
||||
https://www.springframework.org/schema/task/spring-task.xsd">
|
||||
|
||||
<task:annotation-driven mode="aspectj" executor="testExecutor" exception-handler="testExceptionHandler"/>
|
||||
<task:annotation-driven mode="aspectj" executor="testExecutor"
|
||||
exception-handler="testExceptionHandler"/>
|
||||
|
||||
<task:executor id="testExecutor"/>
|
||||
|
||||
<bean id="testExceptionHandler" class="org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler"/>
|
||||
<bean id="testExceptionHandler"
|
||||
class="org.springframework.aop.interceptor.SimpleAsyncUncaughtExceptionHandler"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -42,8 +42,6 @@ import org.springframework.beans.propertyeditors.CustomDateEditor;
|
||||
import org.springframework.beans.testfixture.beans.DerivedTestBean;
|
||||
import org.springframework.beans.testfixture.beans.ITestBean;
|
||||
import org.springframework.beans.testfixture.beans.TestBean;
|
||||
import org.springframework.cglib.proxy.Enhancer;
|
||||
import org.springframework.cglib.proxy.MethodInterceptor;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.ResourceEditor;
|
||||
import org.springframework.lang.Nullable;
|
||||
@@ -54,7 +52,7 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
|
||||
import static org.assertj.core.api.SoftAssertions.assertSoftly;
|
||||
|
||||
/**
|
||||
* Tests for {@link BeanUtils}.
|
||||
* Unit tests for {@link BeanUtils}.
|
||||
*
|
||||
* @author Juergen Hoeller
|
||||
* @author Rob Harrop
|
||||
@@ -138,7 +136,7 @@ class BeanUtilsTests {
|
||||
PropertyDescriptor[] actual = Introspector.getBeanInfo(TestBean.class).getPropertyDescriptors();
|
||||
PropertyDescriptor[] descriptors = BeanUtils.getPropertyDescriptors(TestBean.class);
|
||||
assertThat(descriptors).as("Descriptors should not be null").isNotNull();
|
||||
assertThat(descriptors).as("Invalid number of descriptors returned").hasSameSizeAs(actual);
|
||||
assertThat(descriptors.length).as("Invalid number of descriptors returned").isEqualTo(actual.length);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -164,13 +162,13 @@ class BeanUtilsTests {
|
||||
tb.setAge(32);
|
||||
tb.setTouchy("touchy");
|
||||
TestBean tb2 = new TestBean();
|
||||
assertThat(tb2.getName()).as("Name empty").isNull();
|
||||
assertThat(tb2.getAge()).as("Age empty").isEqualTo(0);
|
||||
assertThat(tb2.getTouchy()).as("Touchy empty").isNull();
|
||||
assertThat(tb2.getName() == null).as("Name empty").isTrue();
|
||||
assertThat(tb2.getAge() == 0).as("Age empty").isTrue();
|
||||
assertThat(tb2.getTouchy() == null).as("Touchy empty").isTrue();
|
||||
BeanUtils.copyProperties(tb, tb2);
|
||||
assertThat(tb2.getName()).as("Name copied").isEqualTo(tb.getName());
|
||||
assertThat(tb2.getAge()).as("Age copied").isEqualTo(tb.getAge());
|
||||
assertThat(tb2.getTouchy()).as("Touchy copied").isEqualTo(tb.getTouchy());
|
||||
assertThat(tb2.getName().equals(tb.getName())).as("Name copied").isTrue();
|
||||
assertThat(tb2.getAge() == tb.getAge()).as("Age copied").isTrue();
|
||||
assertThat(tb2.getTouchy().equals(tb.getTouchy())).as("Touchy copied").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -180,13 +178,13 @@ class BeanUtilsTests {
|
||||
tb.setAge(32);
|
||||
tb.setTouchy("touchy");
|
||||
TestBean tb2 = new TestBean();
|
||||
assertThat(tb2.getName()).as("Name empty").isNull();
|
||||
assertThat(tb2.getAge()).as("Age empty").isEqualTo(0);
|
||||
assertThat(tb2.getTouchy()).as("Touchy empty").isNull();
|
||||
assertThat(tb2.getName() == null).as("Name empty").isTrue();
|
||||
assertThat(tb2.getAge() == 0).as("Age empty").isTrue();
|
||||
assertThat(tb2.getTouchy() == null).as("Touchy empty").isTrue();
|
||||
BeanUtils.copyProperties(tb, tb2);
|
||||
assertThat(tb2.getName()).as("Name copied").isEqualTo(tb.getName());
|
||||
assertThat(tb2.getAge()).as("Age copied").isEqualTo(tb.getAge());
|
||||
assertThat(tb2.getTouchy()).as("Touchy copied").isEqualTo(tb.getTouchy());
|
||||
assertThat(tb2.getName().equals(tb.getName())).as("Name copied").isTrue();
|
||||
assertThat(tb2.getAge() == tb.getAge()).as("Age copied").isTrue();
|
||||
assertThat(tb2.getTouchy().equals(tb.getTouchy())).as("Touchy copied").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -196,13 +194,13 @@ class BeanUtilsTests {
|
||||
tb.setAge(32);
|
||||
tb.setTouchy("touchy");
|
||||
DerivedTestBean tb2 = new DerivedTestBean();
|
||||
assertThat(tb2.getName()).as("Name empty").isNull();
|
||||
assertThat(tb2.getAge()).as("Age empty").isEqualTo(0);
|
||||
assertThat(tb2.getTouchy()).as("Touchy empty").isNull();
|
||||
assertThat(tb2.getName() == null).as("Name empty").isTrue();
|
||||
assertThat(tb2.getAge() == 0).as("Age empty").isTrue();
|
||||
assertThat(tb2.getTouchy() == null).as("Touchy empty").isTrue();
|
||||
BeanUtils.copyProperties(tb, tb2);
|
||||
assertThat(tb2.getName()).as("Name copied").isEqualTo(tb.getName());
|
||||
assertThat(tb2.getAge()).as("Age copied").isEqualTo(tb.getAge());
|
||||
assertThat(tb2.getTouchy()).as("Touchy copied").isEqualTo(tb.getTouchy());
|
||||
assertThat(tb2.getName().equals(tb.getName())).as("Name copied").isTrue();
|
||||
assertThat(tb2.getAge() == tb.getAge()).as("Age copied").isTrue();
|
||||
assertThat(tb2.getTouchy().equals(tb.getTouchy())).as("Touchy copied").isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,8 +227,8 @@ class BeanUtilsTests {
|
||||
IntegerListHolder2 integerListHolder2 = new IntegerListHolder2();
|
||||
|
||||
BeanUtils.copyProperties(integerListHolder1, integerListHolder2);
|
||||
assertThat(integerListHolder1.getList()).containsExactly(42);
|
||||
assertThat(integerListHolder2.getList()).containsExactly(42);
|
||||
assertThat(integerListHolder1.getList()).containsOnly(42);
|
||||
assertThat(integerListHolder2.getList()).containsOnly(42);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -259,7 +257,7 @@ class BeanUtilsTests {
|
||||
WildcardListHolder2 wildcardListHolder2 = new WildcardListHolder2();
|
||||
|
||||
BeanUtils.copyProperties(integerListHolder1, wildcardListHolder2);
|
||||
assertThat(integerListHolder1.getList()).containsExactly(42);
|
||||
assertThat(integerListHolder1.getList()).containsOnly(42);
|
||||
assertThat(wildcardListHolder2.getList()).isEqualTo(Arrays.asList(42));
|
||||
}
|
||||
|
||||
@@ -273,8 +271,9 @@ class BeanUtilsTests {
|
||||
NumberUpperBoundedWildcardListHolder numberListHolder = new NumberUpperBoundedWildcardListHolder();
|
||||
|
||||
BeanUtils.copyProperties(integerListHolder1, numberListHolder);
|
||||
assertThat(integerListHolder1.getList()).containsExactly(42);
|
||||
assertThat(numberListHolder.getList()).isEqualTo(Arrays.asList(42));
|
||||
assertThat(integerListHolder1.getList()).containsOnly(42);
|
||||
assertThat(numberListHolder.getList()).hasSize(1);
|
||||
assertThat(numberListHolder.getList().contains(Integer.valueOf(42))).isTrue();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -283,7 +282,7 @@ class BeanUtilsTests {
|
||||
@Test
|
||||
void copyPropertiesDoesNotCopyFromSuperTypeToSubType() {
|
||||
NumberHolder numberHolder = new NumberHolder();
|
||||
numberHolder.setNumber(42);
|
||||
numberHolder.setNumber(Integer.valueOf(42));
|
||||
IntegerHolder integerHolder = new IntegerHolder();
|
||||
|
||||
BeanUtils.copyProperties(numberHolder, integerHolder);
|
||||
@@ -301,7 +300,7 @@ class BeanUtilsTests {
|
||||
LongListHolder longListHolder = new LongListHolder();
|
||||
|
||||
BeanUtils.copyProperties(integerListHolder, longListHolder);
|
||||
assertThat(integerListHolder.getList()).containsExactly(42);
|
||||
assertThat(integerListHolder.getList()).containsOnly(42);
|
||||
assertThat(longListHolder.getList()).isEmpty();
|
||||
}
|
||||
|
||||
@@ -315,7 +314,7 @@ class BeanUtilsTests {
|
||||
NumberListHolder numberListHolder = new NumberListHolder();
|
||||
|
||||
BeanUtils.copyProperties(integerListHolder, numberListHolder);
|
||||
assertThat(integerListHolder.getList()).containsExactly(42);
|
||||
assertThat(integerListHolder.getList()).containsOnly(42);
|
||||
assertThat(numberListHolder.getList()).isEmpty();
|
||||
}
|
||||
|
||||
@@ -324,13 +323,12 @@ class BeanUtilsTests {
|
||||
Order original = new Order("test", Arrays.asList("foo", "bar"));
|
||||
|
||||
// Create a Proxy that loses the generic type information for the getLineItems() method.
|
||||
OrderSummary proxy = (OrderSummary) Proxy.newProxyInstance(getClass().getClassLoader(),
|
||||
new Class<?>[] {OrderSummary.class}, new OrderInvocationHandler(original));
|
||||
OrderSummary proxy = proxyOrder(original);
|
||||
assertThat(OrderSummary.class.getDeclaredMethod("getLineItems").toGenericString())
|
||||
.contains("java.util.List<java.lang.String>");
|
||||
.contains("java.util.List<java.lang.String>");
|
||||
assertThat(proxy.getClass().getDeclaredMethod("getLineItems").toGenericString())
|
||||
.contains("java.util.List")
|
||||
.doesNotContain("<java.lang.String>");
|
||||
.contains("java.util.List")
|
||||
.doesNotContain("<java.lang.String>");
|
||||
|
||||
// Ensure that our custom Proxy works as expected.
|
||||
assertThat(proxy.getId()).isEqualTo("test");
|
||||
@@ -343,57 +341,40 @@ class BeanUtilsTests {
|
||||
assertThat(target.getLineItems()).containsExactly("foo", "bar");
|
||||
}
|
||||
|
||||
@Test // gh-32888
|
||||
public void copyPropertiesWithGenericCglibClass() {
|
||||
Enhancer enhancer = new Enhancer();
|
||||
enhancer.setSuperclass(User.class);
|
||||
enhancer.setCallback((MethodInterceptor) (obj, method, args, proxy) -> proxy.invokeSuper(obj, args));
|
||||
User user = (User) enhancer.create();
|
||||
user.setId(1);
|
||||
user.setName("proxy");
|
||||
user.setAddress("addr");
|
||||
|
||||
User target = new User();
|
||||
BeanUtils.copyProperties(user, target);
|
||||
assertThat(target.getId()).isEqualTo(user.getId());
|
||||
assertThat(target.getName()).isEqualTo(user.getName());
|
||||
assertThat(target.getAddress()).isEqualTo(user.getAddress());
|
||||
}
|
||||
|
||||
@Test
|
||||
void copyPropertiesWithEditable() throws Exception {
|
||||
TestBean tb = new TestBean();
|
||||
assertThat(tb.getName()).as("Name empty").isNull();
|
||||
assertThat(tb.getName() == null).as("Name empty").isTrue();
|
||||
tb.setAge(32);
|
||||
tb.setTouchy("bla");
|
||||
TestBean tb2 = new TestBean();
|
||||
tb2.setName("rod");
|
||||
assertThat(tb2.getAge()).as("Age empty").isEqualTo(0);
|
||||
assertThat(tb2.getTouchy()).as("Touchy empty").isNull();
|
||||
assertThat(tb2.getAge() == 0).as("Age empty").isTrue();
|
||||
assertThat(tb2.getTouchy() == null).as("Touchy empty").isTrue();
|
||||
|
||||
// "touchy" should not be copied: it's not defined in ITestBean
|
||||
BeanUtils.copyProperties(tb, tb2, ITestBean.class);
|
||||
assertThat(tb2.getName()).as("Name copied").isNull();
|
||||
assertThat(tb2.getAge()).as("Age copied").isEqualTo(32);
|
||||
assertThat(tb2.getTouchy()).as("Touchy still empty").isNull();
|
||||
assertThat(tb2.getName() == null).as("Name copied").isTrue();
|
||||
assertThat(tb2.getAge() == 32).as("Age copied").isTrue();
|
||||
assertThat(tb2.getTouchy() == null).as("Touchy still empty").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
void copyPropertiesWithIgnore() throws Exception {
|
||||
TestBean tb = new TestBean();
|
||||
assertThat(tb.getName()).as("Name empty").isNull();
|
||||
assertThat(tb.getName() == null).as("Name empty").isTrue();
|
||||
tb.setAge(32);
|
||||
tb.setTouchy("bla");
|
||||
TestBean tb2 = new TestBean();
|
||||
tb2.setName("rod");
|
||||
assertThat(tb2.getAge()).as("Age empty").isEqualTo(0);
|
||||
assertThat(tb2.getTouchy()).as("Touchy empty").isNull();
|
||||
assertThat(tb2.getAge() == 0).as("Age empty").isTrue();
|
||||
assertThat(tb2.getTouchy() == null).as("Touchy empty").isTrue();
|
||||
|
||||
// "spouse", "touchy", "age" should not be copied
|
||||
BeanUtils.copyProperties(tb, tb2, "spouse", "touchy", "age");
|
||||
assertThat(tb2.getName()).as("Name copied").isNull();
|
||||
assertThat(tb2.getAge()).as("Age still empty").isEqualTo(0);
|
||||
assertThat(tb2.getTouchy()).as("Touchy still empty").isNull();
|
||||
assertThat(tb2.getName() == null).as("Name copied").isTrue();
|
||||
assertThat(tb2.getAge() == 0).as("Age still empty").isTrue();
|
||||
assertThat(tb2.getTouchy() == null).as("Touchy still empty").isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -402,7 +383,7 @@ class BeanUtilsTests {
|
||||
source.setName("name");
|
||||
TestBean target = new TestBean();
|
||||
BeanUtils.copyProperties(source, target, "specialProperty");
|
||||
assertThat(target.getName()).isEqualTo("name");
|
||||
assertThat("name").isEqualTo(target.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -539,7 +520,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class IntegerHolder {
|
||||
|
||||
@@ -554,7 +534,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class WildcardListHolder1 {
|
||||
|
||||
@@ -569,7 +548,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class WildcardListHolder2 {
|
||||
|
||||
@@ -584,7 +562,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class NumberUpperBoundedWildcardListHolder {
|
||||
|
||||
@@ -599,7 +576,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class NumberListHolder {
|
||||
|
||||
@@ -614,7 +590,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class IntegerListHolder1 {
|
||||
|
||||
@@ -629,7 +604,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class IntegerListHolder2 {
|
||||
|
||||
@@ -644,7 +618,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class LongListHolder {
|
||||
|
||||
@@ -825,7 +798,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class BeanWithNullableTypes {
|
||||
|
||||
private Integer counter;
|
||||
@@ -856,7 +828,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class BeanWithPrimitiveTypes {
|
||||
|
||||
private boolean flag;
|
||||
@@ -869,6 +840,7 @@ class BeanUtilsTests {
|
||||
private char character;
|
||||
private String text;
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public BeanWithPrimitiveTypes(boolean flag, byte byteCount, short shortCount, int intCount, long longCount,
|
||||
float floatCount, double doubleCount, char character, String text) {
|
||||
@@ -919,8 +891,8 @@ class BeanUtilsTests {
|
||||
public String getText() {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static class PrivateBeanWithPrivateConstructor {
|
||||
|
||||
@@ -928,14 +900,13 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class Order {
|
||||
|
||||
private String id;
|
||||
|
||||
private List<String> lineItems;
|
||||
|
||||
|
||||
Order() {
|
||||
}
|
||||
|
||||
@@ -966,7 +937,6 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private interface OrderSummary {
|
||||
|
||||
String getId();
|
||||
@@ -975,10 +945,17 @@ class BeanUtilsTests {
|
||||
}
|
||||
|
||||
|
||||
private OrderSummary proxyOrder(Order order) {
|
||||
return (OrderSummary) Proxy.newProxyInstance(getClass().getClassLoader(),
|
||||
new Class<?>[] { OrderSummary.class }, new OrderInvocationHandler(order));
|
||||
}
|
||||
|
||||
|
||||
private static class OrderInvocationHandler implements InvocationHandler {
|
||||
|
||||
private final Order order;
|
||||
|
||||
|
||||
OrderInvocationHandler(Order order) {
|
||||
this.order = order;
|
||||
}
|
||||
@@ -996,46 +973,4 @@ class BeanUtilsTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class GenericBaseModel<T> {
|
||||
|
||||
private T id;
|
||||
|
||||
private String name;
|
||||
|
||||
public T getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(T id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class User extends GenericBaseModel<Integer> {
|
||||
|
||||
private String address;
|
||||
|
||||
public User() {
|
||||
super();
|
||||
}
|
||||
|
||||
public String getAddress() {
|
||||
return address;
|
||||
}
|
||||
|
||||
public void setAddress(String address) {
|
||||
this.address = address;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+6
-14
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2023 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,11 +45,7 @@ import org.springframework.lang.Nullable;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Spring's default implementation of the {@link LifecycleProcessor} strategy.
|
||||
*
|
||||
* <p>Provides interaction with {@link Lifecycle} and {@link SmartLifecycle} beans in
|
||||
* groups for specific phases, on startup/shutdown as well as for explicit start/stop
|
||||
* interactions on a {@link org.springframework.context.ConfigurableApplicationContext}.
|
||||
* Default implementation of the {@link LifecycleProcessor} strategy.
|
||||
*
|
||||
* @author Mark Fisher
|
||||
* @author Juergen Hoeller
|
||||
@@ -149,13 +145,13 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||
|
||||
lifecycleBeans.forEach((beanName, bean) -> {
|
||||
if (!autoStartupOnly || (bean instanceof SmartLifecycle && ((SmartLifecycle) bean).isAutoStartup())) {
|
||||
int startupPhase = getPhase(bean);
|
||||
phases.computeIfAbsent(startupPhase,
|
||||
phase -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
|
||||
int phase = getPhase(bean);
|
||||
phases.computeIfAbsent(
|
||||
phase,
|
||||
p -> new LifecycleGroup(phase, this.timeoutPerShutdownPhase, lifecycleBeans, autoStartupOnly)
|
||||
).add(beanName, bean);
|
||||
}
|
||||
});
|
||||
|
||||
if (!phases.isEmpty()) {
|
||||
phases.values().forEach(LifecycleGroup::start);
|
||||
}
|
||||
@@ -195,7 +191,6 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||
private void stopBeans() {
|
||||
Map<String, Lifecycle> lifecycleBeans = getLifecycleBeans();
|
||||
Map<Integer, LifecycleGroup> phases = new HashMap<>();
|
||||
|
||||
lifecycleBeans.forEach((beanName, bean) -> {
|
||||
int shutdownPhase = getPhase(bean);
|
||||
LifecycleGroup group = phases.get(shutdownPhase);
|
||||
@@ -205,7 +200,6 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||
}
|
||||
group.add(beanName, bean);
|
||||
});
|
||||
|
||||
if (!phases.isEmpty()) {
|
||||
List<Integer> keys = new ArrayList<>(phases.keySet());
|
||||
keys.sort(Collections.reverseOrder());
|
||||
@@ -320,8 +314,6 @@ public class DefaultLifecycleProcessor implements LifecycleProcessor, BeanFactor
|
||||
/**
|
||||
* Helper class for maintaining a group of Lifecycle beans that should be started
|
||||
* and stopped together based on their 'phase' value (or the default value of 0).
|
||||
* The group is expected to be created in an ad-hoc fashion and group members are
|
||||
* expected to always have the same 'phase' value.
|
||||
*/
|
||||
private class LifecycleGroup {
|
||||
|
||||
|
||||
+4
-28
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2021 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,10 +22,8 @@ import java.text.SimpleDateFormat;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.EnumMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.springframework.format.Formatter;
|
||||
@@ -37,14 +35,9 @@ import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* A formatter for {@link java.util.Date} types.
|
||||
*
|
||||
* <p>Supports the configuration of an explicit date time pattern, timezone,
|
||||
* locale, and fallback date time patterns for lenient parsing.
|
||||
*
|
||||
* <p>Common ISO patterns for UTC instants are applied at millisecond precision.
|
||||
* Note that {@link org.springframework.format.datetime.standard.InstantFormatter}
|
||||
* is recommended for flexible UTC parsing into a {@link java.time.Instant} instead.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Juergen Hoeller
|
||||
* @author Phillip Webb
|
||||
@@ -58,21 +51,12 @@ public class DateFormatter implements Formatter<Date> {
|
||||
|
||||
private static final Map<ISO, String> ISO_PATTERNS;
|
||||
|
||||
private static final Map<ISO, String> ISO_FALLBACK_PATTERNS;
|
||||
|
||||
static {
|
||||
// We use an EnumMap instead of Map.of(...) since the former provides better performance.
|
||||
Map<ISO, String> formats = new EnumMap<>(ISO.class);
|
||||
formats.put(ISO.DATE, "yyyy-MM-dd");
|
||||
formats.put(ISO.TIME, "HH:mm:ss.SSSXXX");
|
||||
formats.put(ISO.DATE_TIME, "yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
|
||||
ISO_PATTERNS = Collections.unmodifiableMap(formats);
|
||||
|
||||
// Fallback format for the time part without milliseconds.
|
||||
Map<ISO, String> fallbackFormats = new EnumMap<>(ISO.class);
|
||||
fallbackFormats.put(ISO.TIME, "HH:mm:ssXXX");
|
||||
fallbackFormats.put(ISO.DATE_TIME, "yyyy-MM-dd'T'HH:mm:ssXXX");
|
||||
ISO_FALLBACK_PATTERNS = Collections.unmodifiableMap(fallbackFormats);
|
||||
}
|
||||
|
||||
|
||||
@@ -217,16 +201,8 @@ public class DateFormatter implements Formatter<Date> {
|
||||
return getDateFormat(locale).parse(text);
|
||||
}
|
||||
catch (ParseException ex) {
|
||||
Set<String> fallbackPatterns = new LinkedHashSet<>();
|
||||
String isoPattern = ISO_FALLBACK_PATTERNS.get(this.iso);
|
||||
if (isoPattern != null) {
|
||||
fallbackPatterns.add(isoPattern);
|
||||
}
|
||||
if (!ObjectUtils.isEmpty(this.fallbackPatterns)) {
|
||||
Collections.addAll(fallbackPatterns, this.fallbackPatterns);
|
||||
}
|
||||
if (!fallbackPatterns.isEmpty()) {
|
||||
for (String pattern : fallbackPatterns) {
|
||||
for (String pattern : this.fallbackPatterns) {
|
||||
try {
|
||||
DateFormat dateFormat = configureDateFormat(new SimpleDateFormat(pattern, locale));
|
||||
// Align timezone for parsing format with printing format if ISO is set.
|
||||
@@ -244,8 +220,8 @@ public class DateFormatter implements Formatter<Date> {
|
||||
}
|
||||
if (this.source != null) {
|
||||
ParseException parseException = new ParseException(
|
||||
String.format("Unable to parse date time value \"%s\" using configuration from %s", text, this.source),
|
||||
ex.getErrorOffset());
|
||||
String.format("Unable to parse date time value \"%s\" using configuration from %s", text, this.source),
|
||||
ex.getErrorOffset());
|
||||
parseException.initCause(ex);
|
||||
throw parseException;
|
||||
}
|
||||
|
||||
+3
-3
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2019 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.
|
||||
@@ -41,12 +41,12 @@ public class InstantFormatter implements Formatter<Instant> {
|
||||
|
||||
@Override
|
||||
public Instant parse(String text, Locale locale) throws ParseException {
|
||||
if (!text.isEmpty() && Character.isAlphabetic(text.charAt(0))) {
|
||||
if (text.length() > 0 && Character.isAlphabetic(text.charAt(0))) {
|
||||
// assuming RFC-1123 value a la "Tue, 3 Jun 2008 11:05:30 GMT"
|
||||
return Instant.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse(text));
|
||||
}
|
||||
else {
|
||||
// assuming UTC instant a la "2007-12-03T10:15:30.000Z"
|
||||
// assuming UTC instant a la "2007-12-03T10:15:30.00Z"
|
||||
return Instant.parse(text);
|
||||
}
|
||||
}
|
||||
|
||||
+6
-3
@@ -28,14 +28,17 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
*
|
||||
* @author Adrian Colyer
|
||||
* @author Chris Beams
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
class OverloadedAdviceTests {
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("resource")
|
||||
void testConfigParsingWithMismatchedAdviceMethod() {
|
||||
new ClassPathXmlApplicationContext(getClass().getSimpleName() + ".xml", getClass());
|
||||
void testExceptionOnConfigParsingWithMismatchedAdviceMethod() {
|
||||
assertThatExceptionOfType(BeanCreationException.class)
|
||||
.isThrownBy(() -> new ClassPathXmlApplicationContext(getClass().getSimpleName() + ".xml", getClass()))
|
||||
.havingRootCause()
|
||||
.isInstanceOf(IllegalArgumentException.class)
|
||||
.as("invalidAbsoluteTypeName should be detected by AJ").withMessageContaining("invalidAbsoluteTypeName");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
+57
-36
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -23,6 +23,9 @@ import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
|
||||
import org.joda.time.DateTimeZone;
|
||||
import org.joda.time.format.DateTimeFormat;
|
||||
import org.joda.time.format.DateTimeFormatter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
@@ -30,88 +33,83 @@ import org.springframework.format.annotation.DateTimeFormat.ISO;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Tests for {@link DateFormatter}.
|
||||
*
|
||||
* @author Keith Donald
|
||||
* @author Phillip Webb
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
class DateFormatterTests {
|
||||
public class DateFormatterTests {
|
||||
|
||||
private static final TimeZone UTC = TimeZone.getTimeZone("UTC");
|
||||
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseDefault() throws Exception {
|
||||
public void shouldPrintAndParseDefault() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("Jun 1, 2009");
|
||||
assertThat(formatter.parse("Jun 1, 2009", Locale.US)).isEqualTo(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseFromPattern() throws ParseException {
|
||||
public void shouldPrintAndParseFromPattern() throws ParseException {
|
||||
DateFormatter formatter = new DateFormatter("yyyy-MM-dd");
|
||||
formatter.setTimeZone(UTC);
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("2009-06-01");
|
||||
assertThat(formatter.parse("2009-06-01", Locale.US)).isEqualTo(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseShort() throws Exception {
|
||||
public void shouldPrintAndParseShort() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setStyle(DateFormat.SHORT);
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("6/1/09");
|
||||
assertThat(formatter.parse("6/1/09", Locale.US)).isEqualTo(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseMedium() throws Exception {
|
||||
public void shouldPrintAndParseMedium() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setStyle(DateFormat.MEDIUM);
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("Jun 1, 2009");
|
||||
assertThat(formatter.parse("Jun 1, 2009", Locale.US)).isEqualTo(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseLong() throws Exception {
|
||||
public void shouldPrintAndParseLong() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setStyle(DateFormat.LONG);
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("June 1, 2009");
|
||||
assertThat(formatter.parse("June 1, 2009", Locale.US)).isEqualTo(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseFull() throws Exception {
|
||||
public void shouldPrintAndParseFull() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setStyle(DateFormat.FULL);
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("Monday, June 1, 2009");
|
||||
assertThat(formatter.parse("Monday, June 1, 2009", Locale.US)).isEqualTo(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseIsoDate() throws Exception {
|
||||
public void shouldPrintAndParseISODate() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setIso(ISO.DATE);
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1, 14, 23, 5, 3);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("2009-06-01");
|
||||
assertThat(formatter.parse("2009-6-01", Locale.US))
|
||||
@@ -119,56 +117,79 @@ class DateFormatterTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseIsoTime() throws Exception {
|
||||
public void shouldPrintAndParseISOTime() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setIso(ISO.TIME);
|
||||
|
||||
Date date = getDate(2009, Calendar.JANUARY, 1, 14, 23, 5, 3);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("14:23:05.003Z");
|
||||
assertThat(formatter.parse("14:23:05.003Z", Locale.US))
|
||||
.isEqualTo(getDate(1970, Calendar.JANUARY, 1, 14, 23, 5, 3));
|
||||
|
||||
date = getDate(2009, Calendar.JANUARY, 1, 14, 23, 5, 0);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("14:23:05.000Z");
|
||||
assertThat(formatter.parse("14:23:05Z", Locale.US))
|
||||
.isEqualTo(getDate(1970, Calendar.JANUARY, 1, 14, 23, 5, 0).toInstant());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldPrintAndParseIsoDateTime() throws Exception {
|
||||
public void shouldPrintAndParseISODateTime() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setIso(ISO.DATE_TIME);
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1, 14, 23, 5, 3);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("2009-06-01T14:23:05.003Z");
|
||||
assertThat(formatter.parse("2009-06-01T14:23:05.003Z", Locale.US)).isEqualTo(date);
|
||||
|
||||
date = getDate(2009, Calendar.JUNE, 1, 14, 23, 5, 0);
|
||||
assertThat(formatter.print(date, Locale.US)).isEqualTo("2009-06-01T14:23:05.000Z");
|
||||
assertThat(formatter.parse("2009-06-01T14:23:05Z", Locale.US)).isEqualTo(date.toInstant());
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldThrowOnUnsupportedStylePattern() {
|
||||
public void shouldSupportJodaStylePatterns() throws Exception {
|
||||
String[] chars = { "S", "M", "-" };
|
||||
for (String d : chars) {
|
||||
for (String t : chars) {
|
||||
String style = d + t;
|
||||
if (!style.equals("--")) {
|
||||
Date date = getDate(2009, Calendar.JUNE, 10, 14, 23, 0, 0);
|
||||
if (t.equals("-")) {
|
||||
date = getDate(2009, Calendar.JUNE, 10);
|
||||
}
|
||||
else if (d.equals("-")) {
|
||||
date = getDate(1970, Calendar.JANUARY, 1, 14, 23, 0, 0);
|
||||
}
|
||||
testJodaStylePatterns(style, Locale.US, date);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void testJodaStylePatterns(String style, Locale locale, Date date) throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setStylePattern(style);
|
||||
DateTimeFormatter jodaFormatter = DateTimeFormat.forStyle(style).withLocale(locale).withZone(DateTimeZone.UTC);
|
||||
String jodaPrinted = jodaFormatter.print(date.getTime());
|
||||
assertThat(formatter.print(date, locale))
|
||||
.as("Unable to print style pattern " + style)
|
||||
.isEqualTo(jodaPrinted);
|
||||
assertThat(formatter.parse(jodaPrinted, locale))
|
||||
.as("Unable to parse style pattern " + style)
|
||||
.isEqualTo(date);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldThrowOnUnsupportedStylePattern() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setStylePattern("OO");
|
||||
|
||||
assertThatIllegalStateException().isThrownBy(() -> formatter.parse("2009", Locale.US))
|
||||
.withMessageContaining("Unsupported style pattern 'OO'");
|
||||
assertThatIllegalStateException().isThrownBy(() ->
|
||||
formatter.parse("2009", Locale.US))
|
||||
.withMessageContaining("Unsupported style pattern 'OO'");
|
||||
}
|
||||
|
||||
@Test
|
||||
void shouldUseCorrectOrder() {
|
||||
public void shouldUseCorrectOrder() throws Exception {
|
||||
DateFormatter formatter = new DateFormatter();
|
||||
formatter.setTimeZone(UTC);
|
||||
formatter.setStyle(DateFormat.SHORT);
|
||||
formatter.setStylePattern("L-");
|
||||
formatter.setIso(ISO.DATE_TIME);
|
||||
formatter.setPattern("yyyy");
|
||||
|
||||
Date date = getDate(2009, Calendar.JUNE, 1, 14, 23, 5, 3);
|
||||
|
||||
assertThat(formatter.print(date, Locale.US)).as("uses pattern").isEqualTo("2009");
|
||||
|
||||
formatter.setPattern("");
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -52,7 +52,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* @author Juergen Hoeller
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
class DateFormattingTests {
|
||||
public class DateFormattingTests {
|
||||
|
||||
private final FormattingConversionService conversionService = new FormattingConversionService();
|
||||
|
||||
|
||||
+59
-57
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -105,7 +105,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDate", "10/31/09");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("localDate")).isEqualTo("10/31/09");
|
||||
}
|
||||
|
||||
@@ -117,7 +117,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDate", "October 31, 2009");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("localDate")).isEqualTo("October 31, 2009");
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDate", "20091031");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("localDate")).isEqualTo("20091031");
|
||||
}
|
||||
|
||||
@@ -138,7 +138,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDate", new String[] {"10/31/09"});
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -146,7 +146,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("styleLocalDate", "Oct 31, 2009");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("styleLocalDate")).isEqualTo("Oct 31, 2009");
|
||||
}
|
||||
|
||||
@@ -164,7 +164,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("children[0].styleLocalDate", "Oct 31, 2009");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("children[0].styleLocalDate")).isEqualTo("Oct 31, 2009");
|
||||
}
|
||||
|
||||
@@ -174,7 +174,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("styleLocalDate", "Oct 31, 2009");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("styleLocalDate")).isEqualTo("Oct 31, 2009");
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDate", new GregorianCalendar(2009, 9, 31, 0, 0));
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("localDate")).isEqualTo("10/31/09");
|
||||
}
|
||||
|
||||
@@ -202,7 +202,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localTime", "12:00 PM");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("localTime")).isEqualTo("12:00 PM");
|
||||
}
|
||||
|
||||
@@ -214,7 +214,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localTime", "12:00:00 PM");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("localTime")).isEqualTo("12:00:00 PM");
|
||||
}
|
||||
|
||||
@@ -226,7 +226,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localTime", "130000");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("localTime")).isEqualTo("130000");
|
||||
}
|
||||
|
||||
@@ -235,7 +235,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("styleLocalTime", "12:00:00 PM");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("styleLocalTime")).isEqualTo("12:00:00 PM");
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localTime", new GregorianCalendar(1970, 0, 0, 12, 0));
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("localTime")).isEqualTo("12:00 PM");
|
||||
}
|
||||
|
||||
@@ -253,9 +253,10 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDateTime", LocalDateTime.of(2009, 10, 31, 12, 0));
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
String value = binder.getBindingResult().getFieldValue("localDateTime").toString();
|
||||
assertThat(value).startsWith("10/31/09").endsWith("12:00 PM");
|
||||
assertThat(value.startsWith("10/31/09")).isTrue();
|
||||
assertThat(value.endsWith("12:00 PM")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -263,9 +264,10 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("styleLocalDateTime", LocalDateTime.of(2009, 10, 31, 12, 0));
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
String value = binder.getBindingResult().getFieldValue("styleLocalDateTime").toString();
|
||||
assertThat(value).startsWith("Oct 31, 2009").endsWith("12:00:00 PM");
|
||||
assertThat(value.startsWith("Oct 31, 2009")).isTrue();
|
||||
assertThat(value.endsWith("12:00:00 PM")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -273,9 +275,10 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDateTime", new GregorianCalendar(2009, 9, 31, 12, 0));
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
String value = binder.getBindingResult().getFieldValue("localDateTime").toString();
|
||||
assertThat(value).startsWith("10/31/09").endsWith("12:00 PM");
|
||||
assertThat(value.startsWith("10/31/09")).isTrue();
|
||||
assertThat(value.endsWith("12:00 PM")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -286,9 +289,10 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("localDateTime", LocalDateTime.of(2009, 10, 31, 12, 0));
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
String value = binder.getBindingResult().getFieldValue("localDateTime").toString();
|
||||
assertThat(value).startsWith("Oct 31, 2009").endsWith("12:00:00 PM");
|
||||
assertThat(value.startsWith("Oct 31, 2009")).isTrue();
|
||||
assertThat(value.endsWith("12:00:00 PM")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -296,7 +300,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("patternLocalDateTime", "10/31/09 12:00 PM");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("patternLocalDateTime")).isEqualTo("10/31/09 12:00 PM");
|
||||
}
|
||||
|
||||
@@ -313,7 +317,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("isoLocalDate", "2009-10-31");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("isoLocalDate")).isEqualTo("2009-10-31");
|
||||
}
|
||||
|
||||
@@ -352,7 +356,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("isoLocalTime", "12:00:00");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("isoLocalTime")).isEqualTo("12:00:00");
|
||||
}
|
||||
|
||||
@@ -361,7 +365,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("isoLocalTime", "12:00:00.000-05:00");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("isoLocalTime")).isEqualTo("12:00:00");
|
||||
}
|
||||
|
||||
@@ -370,7 +374,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("isoLocalDateTime", "2009-10-31T12:00:00");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("isoLocalDateTime")).isEqualTo("2009-10-31T12:00:00");
|
||||
}
|
||||
|
||||
@@ -379,7 +383,7 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("isoLocalDateTime", "2009-10-31T12:00:00.000Z");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("isoLocalDateTime")).isEqualTo("2009-10-31T12:00:00");
|
||||
}
|
||||
|
||||
@@ -388,8 +392,8 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("instant", "2009-10-31T12:00:00.000Z");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("instant").toString()).startsWith("2009-10-31T12:00");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("instant").toString().startsWith("2009-10-31T12:00")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -401,8 +405,8 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("instant", new Date(109, 9, 31, 12, 0));
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("instant").toString()).startsWith("2009-10-31");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("instant").toString().startsWith("2009-10-31")).isTrue();
|
||||
}
|
||||
finally {
|
||||
TimeZone.setDefault(defaultZone);
|
||||
@@ -414,8 +418,8 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("period", "P6Y3M1D");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("period").toString()).isEqualTo("P6Y3M1D");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("period").toString().equals("P6Y3M1D")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -423,8 +427,8 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("duration", "PT8H6M12.345S");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("duration").toString()).isEqualTo("PT8H6M12.345S");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("duration").toString().equals("PT8H6M12.345S")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -432,8 +436,8 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("year", "2007");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("year").toString()).isEqualTo("2007");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("year").toString().equals("2007")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -441,8 +445,8 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("month", "JULY");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("month").toString()).isEqualTo("JULY");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("month").toString().equals("JULY")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -450,8 +454,8 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("month", "July");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("month").toString()).isEqualTo("JULY");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("month").toString().equals("JULY")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -459,8 +463,8 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("yearMonth", "2007-12");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("yearMonth").toString()).isEqualTo("2007-12");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("yearMonth").toString().equals("2007-12")).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -468,11 +472,10 @@ class DateTimeFormattingTests {
|
||||
MutablePropertyValues propertyValues = new MutablePropertyValues();
|
||||
propertyValues.add("monthDay", "--12-03");
|
||||
binder.bind(propertyValues);
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isZero();
|
||||
assertThat(binder.getBindingResult().getFieldValue("monthDay").toString()).isEqualTo("--12-03");
|
||||
assertThat(binder.getBindingResult().getErrorCount()).isEqualTo(0);
|
||||
assertThat(binder.getBindingResult().getFieldValue("monthDay").toString().equals("--12-03")).isTrue();
|
||||
}
|
||||
|
||||
|
||||
@Nested
|
||||
class FallbackPatternTests {
|
||||
|
||||
@@ -484,7 +487,7 @@ class DateTimeFormattingTests {
|
||||
propertyValues.add(propertyName, propertyValue);
|
||||
binder.bind(propertyValues);
|
||||
BindingResult bindingResult = binder.getBindingResult();
|
||||
assertThat(bindingResult.getErrorCount()).isZero();
|
||||
assertThat(bindingResult.getErrorCount()).isEqualTo(0);
|
||||
assertThat(bindingResult.getFieldValue(propertyName)).isEqualTo("3/2/21");
|
||||
}
|
||||
|
||||
@@ -496,12 +499,11 @@ class DateTimeFormattingTests {
|
||||
propertyValues.add(propertyName, propertyValue);
|
||||
binder.bind(propertyValues);
|
||||
BindingResult bindingResult = binder.getBindingResult();
|
||||
assertThat(bindingResult.getErrorCount()).isZero();
|
||||
assertThat(bindingResult.getErrorCount()).isEqualTo(0);
|
||||
assertThat(bindingResult.getFieldValue(propertyName)).isEqualTo("2021-03-02");
|
||||
}
|
||||
|
||||
@ParameterizedTest(name = "input date: {0}")
|
||||
// @ValueSource(strings = {"12:00:00\u202FPM", "12:00:00", "12:00"})
|
||||
@ValueSource(strings = {"12:00:00 PM", "12:00:00", "12:00"})
|
||||
void styleLocalTime(String propertyValue) {
|
||||
String propertyName = "styleLocalTimeWithFallbackPatterns";
|
||||
@@ -509,8 +511,7 @@ class DateTimeFormattingTests {
|
||||
propertyValues.add(propertyName, propertyValue);
|
||||
binder.bind(propertyValues);
|
||||
BindingResult bindingResult = binder.getBindingResult();
|
||||
assertThat(bindingResult.getErrorCount()).isZero();
|
||||
// assertThat(bindingResult.getFieldValue(propertyName)).asString().matches("12:00:00\\SPM");
|
||||
assertThat(bindingResult.getErrorCount()).isEqualTo(0);
|
||||
assertThat(bindingResult.getFieldValue(propertyName)).isEqualTo("12:00:00 PM");
|
||||
}
|
||||
|
||||
@@ -522,7 +523,7 @@ class DateTimeFormattingTests {
|
||||
propertyValues.add(propertyName, propertyValue);
|
||||
binder.bind(propertyValues);
|
||||
BindingResult bindingResult = binder.getBindingResult();
|
||||
assertThat(bindingResult.getErrorCount()).isZero();
|
||||
assertThat(bindingResult.getErrorCount()).isEqualTo(0);
|
||||
assertThat(bindingResult.getFieldValue(propertyName)).isEqualTo("2021-03-02T12:00:00");
|
||||
}
|
||||
|
||||
@@ -564,10 +565,10 @@ class DateTimeFormattingTests {
|
||||
@DateTimeFormat(style = "M-")
|
||||
private LocalDate styleLocalDate;
|
||||
|
||||
@DateTimeFormat(style = "S-", fallbackPatterns = {"yyyy-MM-dd", "yyyyMMdd", "yyyy.MM.dd"})
|
||||
@DateTimeFormat(style = "S-", fallbackPatterns = { "yyyy-MM-dd", "yyyyMMdd", "yyyy.MM.dd" })
|
||||
private LocalDate styleLocalDateWithFallbackPatterns;
|
||||
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd", fallbackPatterns = {"M/d/yy", "yyyyMMdd", "yyyy.MM.dd"})
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd", fallbackPatterns = { "M/d/yy", "yyyyMMdd", "yyyy.MM.dd" })
|
||||
private LocalDate patternLocalDateWithFallbackPatterns;
|
||||
|
||||
private LocalTime localTime;
|
||||
@@ -575,7 +576,7 @@ class DateTimeFormattingTests {
|
||||
@DateTimeFormat(style = "-M")
|
||||
private LocalTime styleLocalTime;
|
||||
|
||||
@DateTimeFormat(style = "-M", fallbackPatterns = {"HH:mm:ss", "HH:mm"})
|
||||
@DateTimeFormat(style = "-M", fallbackPatterns = { "HH:mm:ss", "HH:mm"})
|
||||
private LocalTime styleLocalTimeWithFallbackPatterns;
|
||||
|
||||
private LocalDateTime localDateTime;
|
||||
@@ -595,7 +596,7 @@ class DateTimeFormattingTests {
|
||||
@DateTimeFormat(iso = ISO.DATE_TIME)
|
||||
private LocalDateTime isoLocalDateTime;
|
||||
|
||||
@DateTimeFormat(iso = ISO.DATE_TIME, fallbackPatterns = {"yyyy-MM-dd HH:mm:ss", "M/d/yy HH:mm"})
|
||||
@DateTimeFormat(iso = ISO.DATE_TIME, fallbackPatterns = { "yyyy-MM-dd HH:mm:ss", "M/d/yy HH:mm"})
|
||||
private LocalDateTime isoLocalDateTimeWithFallbackPatterns;
|
||||
|
||||
private Instant instant;
|
||||
@@ -614,6 +615,7 @@ class DateTimeFormattingTests {
|
||||
|
||||
private final List<DateTimeBean> children = new ArrayList<>();
|
||||
|
||||
|
||||
public LocalDate getLocalDate() {
|
||||
return this.localDate;
|
||||
}
|
||||
|
||||
+10
-9
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2019 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,7 +19,6 @@ package org.springframework.format.datetime.standard;
|
||||
import java.text.ParseException;
|
||||
import java.time.Instant;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Locale;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -50,12 +49,13 @@ class InstantFormatterTests {
|
||||
|
||||
private final InstantFormatter instantFormatter = new InstantFormatter();
|
||||
|
||||
|
||||
@ParameterizedTest
|
||||
@ArgumentsSource(ISOSerializedInstantProvider.class)
|
||||
void should_parse_an_ISO_formatted_string_representation_of_an_Instant(String input) throws ParseException {
|
||||
Instant expected = DateTimeFormatter.ISO_INSTANT.parse(input, Instant::from);
|
||||
Instant actual = instantFormatter.parse(input, Locale.US);
|
||||
|
||||
Instant actual = instantFormatter.parse(input, null);
|
||||
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@@ -63,7 +63,9 @@ class InstantFormatterTests {
|
||||
@ArgumentsSource(RFC1123SerializedInstantProvider.class)
|
||||
void should_parse_an_RFC1123_formatted_string_representation_of_an_Instant(String input) throws ParseException {
|
||||
Instant expected = DateTimeFormatter.RFC_1123_DATE_TIME.parse(input, Instant::from);
|
||||
Instant actual = instantFormatter.parse(input, Locale.US);
|
||||
|
||||
Instant actual = instantFormatter.parse(input, null);
|
||||
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
@@ -71,11 +73,12 @@ class InstantFormatterTests {
|
||||
@ArgumentsSource(RandomInstantProvider.class)
|
||||
void should_serialize_an_Instant_using_ISO_format_and_ignoring_Locale(Instant input) {
|
||||
String expected = DateTimeFormatter.ISO_INSTANT.format(input);
|
||||
String actual = instantFormatter.print(input, Locale.US);
|
||||
|
||||
String actual = instantFormatter.print(input, null);
|
||||
|
||||
assertThat(actual).isEqualTo(expected);
|
||||
}
|
||||
|
||||
|
||||
private static class RandomInstantProvider implements ArgumentsProvider {
|
||||
|
||||
private static final long DATA_SET_SIZE = 10;
|
||||
@@ -97,7 +100,6 @@ class InstantFormatterTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class ISOSerializedInstantProvider extends RandomInstantProvider {
|
||||
|
||||
@Override
|
||||
@@ -106,7 +108,6 @@ class InstantFormatterTests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static class RFC1123SerializedInstantProvider extends RandomInstantProvider {
|
||||
|
||||
// RFC-1123 supports only 4-digit years
|
||||
|
||||
-2
@@ -18,6 +18,4 @@
|
||||
|
||||
<bean id="testBean" class="org.springframework.beans.testfixture.beans.TestBean"/>
|
||||
|
||||
<bean id="testBean2" class="org.springframework.beans.testfixture.beans.TestBean"/>
|
||||
|
||||
</beans>
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -57,11 +57,11 @@ public final class BridgeMethodResolver {
|
||||
|
||||
|
||||
/**
|
||||
* Find the local original method for the supplied {@link Method bridge Method}.
|
||||
* Find the original method for the supplied {@link Method bridge Method}.
|
||||
* <p>It is safe to call this method passing in a non-bridge {@link Method} instance.
|
||||
* In such a case, the supplied {@link Method} instance is returned directly to the caller.
|
||||
* Callers are <strong>not</strong> required to check for bridging before calling this method.
|
||||
* @param bridgeMethod the method to introspect against its declaring class
|
||||
* @param bridgeMethod the method to introspect
|
||||
* @return the original method (either the bridged method or the passed-in method
|
||||
* if no more specific one could be found)
|
||||
*/
|
||||
@@ -73,7 +73,8 @@ public final class BridgeMethodResolver {
|
||||
if (bridgedMethod == null) {
|
||||
// Gather all methods with matching name and parameter size.
|
||||
List<Method> candidateMethods = new ArrayList<>();
|
||||
MethodFilter filter = (candidateMethod -> isBridgedCandidateFor(candidateMethod, bridgeMethod));
|
||||
MethodFilter filter = candidateMethod ->
|
||||
isBridgedCandidateFor(candidateMethod, bridgeMethod);
|
||||
ReflectionUtils.doWithMethods(bridgeMethod.getDeclaringClass(), candidateMethods::add, filter);
|
||||
if (!candidateMethods.isEmpty()) {
|
||||
bridgedMethod = candidateMethods.size() == 1 ?
|
||||
@@ -94,10 +95,10 @@ public final class BridgeMethodResolver {
|
||||
* Returns {@code true} if the supplied '{@code candidateMethod}' can be
|
||||
* considered a valid candidate for the {@link Method} that is {@link Method#isBridge() bridged}
|
||||
* by the supplied {@link Method bridge Method}. This method performs inexpensive
|
||||
* checks and can be used to quickly filter for a set of possible matches.
|
||||
* checks and can be used quickly to filter for a set of possible matches.
|
||||
*/
|
||||
private static boolean isBridgedCandidateFor(Method candidateMethod, Method bridgeMethod) {
|
||||
return (!candidateMethod.isBridge() &&
|
||||
return (!candidateMethod.isBridge() && !candidateMethod.equals(bridgeMethod) &&
|
||||
candidateMethod.getName().equals(bridgeMethod.getName()) &&
|
||||
candidateMethod.getParameterCount() == bridgeMethod.getParameterCount());
|
||||
}
|
||||
@@ -120,8 +121,8 @@ public final class BridgeMethodResolver {
|
||||
return candidateMethod;
|
||||
}
|
||||
else if (previousMethod != null) {
|
||||
sameSig = sameSig && Arrays.equals(
|
||||
candidateMethod.getGenericParameterTypes(), previousMethod.getGenericParameterTypes());
|
||||
sameSig = sameSig &&
|
||||
Arrays.equals(candidateMethod.getGenericParameterTypes(), previousMethod.getGenericParameterTypes());
|
||||
}
|
||||
previousMethod = candidateMethod;
|
||||
}
|
||||
@@ -162,8 +163,7 @@ public final class BridgeMethodResolver {
|
||||
}
|
||||
}
|
||||
// A non-array type: compare the type itself.
|
||||
if (!ClassUtils.resolvePrimitiveIfNecessary(candidateParameter).equals(
|
||||
ClassUtils.resolvePrimitiveIfNecessary(genericParameter.toClass()))) {
|
||||
if (!ClassUtils.resolvePrimitiveIfNecessary(candidateParameter).equals(ClassUtils.resolvePrimitiveIfNecessary(genericParameter.toClass()))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -226,8 +226,8 @@ public final class BridgeMethodResolver {
|
||||
/**
|
||||
* Compare the signatures of the bridge method and the method which it bridges. If
|
||||
* the parameter and return types are the same, it is a 'visibility' bridge method
|
||||
* introduced in Java 6 to fix <a href="https://bugs.openjdk.org/browse/JDK-6342411">
|
||||
* JDK-6342411</a>.
|
||||
* introduced in Java 6 to fix https://bugs.openjdk.org/browse/JDK-6342411.
|
||||
* See also https://stas-blogspot.blogspot.com/2010/03/java-bridge-methods-explained.html
|
||||
* @return whether signatures match as described
|
||||
*/
|
||||
public static boolean isVisibilityBridgeMethodPair(Method bridgeMethod, Method bridgedMethod) {
|
||||
|
||||
@@ -1052,16 +1052,16 @@ public abstract class AnnotationUtils {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
for (Method method : annotation.annotationType().getDeclaredMethods()) {
|
||||
if (method.getName().equals(attributeName) && method.getParameterCount() == 0) {
|
||||
return invokeAnnotationMethod(method, annotation);
|
||||
}
|
||||
}
|
||||
Method method = annotation.annotationType().getDeclaredMethod(attributeName);
|
||||
return invokeAnnotationMethod(method, annotation);
|
||||
}
|
||||
catch (NoSuchMethodException ex) {
|
||||
return null;
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
handleValueRetrievalFailure(annotation, ex);
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+12
-13
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2023 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.
|
||||
@@ -226,8 +226,6 @@ public class Indexer extends SpelNodeImpl {
|
||||
cf.loadTarget(mv);
|
||||
}
|
||||
|
||||
SpelNodeImpl index = this.children[0];
|
||||
|
||||
if (this.indexedType == IndexedType.ARRAY) {
|
||||
int insn;
|
||||
if ("D".equals(this.exitTypeDescriptor)) {
|
||||
@@ -264,14 +262,18 @@ public class Indexer extends SpelNodeImpl {
|
||||
//depthPlusOne(exitTypeDescriptor)+"Ljava/lang/Object;");
|
||||
insn = AALOAD;
|
||||
}
|
||||
|
||||
generateIndexCode(mv, cf, index, int.class);
|
||||
SpelNodeImpl index = this.children[0];
|
||||
cf.enterCompilationScope();
|
||||
index.generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
mv.visitInsn(insn);
|
||||
}
|
||||
|
||||
else if (this.indexedType == IndexedType.LIST) {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/util/List");
|
||||
generateIndexCode(mv, cf, index, int.class);
|
||||
cf.enterCompilationScope();
|
||||
this.children[0].generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
mv.visitMethodInsn(INVOKEINTERFACE, "java/util/List", "get", "(I)Ljava/lang/Object;", true);
|
||||
}
|
||||
|
||||
@@ -279,13 +281,15 @@ public class Indexer extends SpelNodeImpl {
|
||||
mv.visitTypeInsn(CHECKCAST, "java/util/Map");
|
||||
// Special case when the key is an unquoted string literal that will be parsed as
|
||||
// a property/field reference
|
||||
if (index instanceof PropertyOrFieldReference) {
|
||||
if ((this.children[0] instanceof PropertyOrFieldReference)) {
|
||||
PropertyOrFieldReference reference = (PropertyOrFieldReference) this.children[0];
|
||||
String mapKeyName = reference.getName();
|
||||
mv.visitLdcInsn(mapKeyName);
|
||||
}
|
||||
else {
|
||||
generateIndexCode(mv, cf, index, Object.class);
|
||||
cf.enterCompilationScope();
|
||||
this.children[0].generateCode(mv, cf);
|
||||
cf.exitCompilationScope();
|
||||
}
|
||||
mv.visitMethodInsn(
|
||||
INVOKEINTERFACE, "java/util/Map", "get", "(Ljava/lang/Object;)Ljava/lang/Object;", true);
|
||||
@@ -321,11 +325,6 @@ public class Indexer extends SpelNodeImpl {
|
||||
cf.pushDescriptor(this.exitTypeDescriptor);
|
||||
}
|
||||
|
||||
private void generateIndexCode(MethodVisitor mv, CodeFlow cf, SpelNodeImpl indexNode, Class<?> indexType) {
|
||||
String indexDesc = CodeFlow.toDescriptor(indexType);
|
||||
generateCodeForArgument(mv, cf, indexNode, indexDesc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toStringAST() {
|
||||
StringJoiner sj = new StringJoiner(",", "[", "]");
|
||||
|
||||
+1
-489
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2022 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,8 +20,6 @@ import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
@@ -29,10 +27,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.asm.MethodVisitor;
|
||||
@@ -60,7 +55,6 @@ import static org.assertj.core.api.InstanceOfAssertFactories.BOOLEAN;
|
||||
* Checks SpelCompiler behavior. This should cover compilation all compiled node types.
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
@@ -135,488 +129,6 @@ public class SpelCompilationCoverageTests extends AbstractExpressionTests {
|
||||
private SpelNodeImpl ast;
|
||||
|
||||
|
||||
@Nested
|
||||
class VariableReferenceTests {
|
||||
|
||||
@Test
|
||||
void userDefinedVariable() {
|
||||
EvaluationContext ctx = new StandardEvaluationContext();
|
||||
ctx.setVariable("target", "abc");
|
||||
expression = parser.parseExpression("#target");
|
||||
assertThat(expression.getValue(ctx)).isEqualTo("abc");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(ctx)).isEqualTo("abc");
|
||||
ctx.setVariable("target", "123");
|
||||
assertThat(expression.getValue(ctx)).isEqualTo("123");
|
||||
|
||||
// Changing the variable type from String to Integer results in a
|
||||
// ClassCastException in the compiled code.
|
||||
ctx.setVariable("target", 42);
|
||||
assertThatExceptionOfType(SpelEvaluationException.class)
|
||||
.isThrownBy(() -> expression.getValue(ctx))
|
||||
.withCauseInstanceOf(ClassCastException.class);
|
||||
|
||||
ctx.setVariable("target", "abc");
|
||||
expression = parser.parseExpression("#target.charAt(0)");
|
||||
assertThat(expression.getValue(ctx)).isEqualTo('a');
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(ctx)).isEqualTo('a');
|
||||
ctx.setVariable("target", "1");
|
||||
assertThat(expression.getValue(ctx)).isEqualTo('1');
|
||||
|
||||
// Changing the variable type from String to Integer results in a
|
||||
// ClassCastException in the compiled code.
|
||||
ctx.setVariable("target", 42);
|
||||
assertThatExceptionOfType(SpelEvaluationException.class)
|
||||
.isThrownBy(() -> expression.getValue(ctx))
|
||||
.withCauseInstanceOf(ClassCastException.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Nested
|
||||
class IndexingTests {
|
||||
|
||||
@Test
|
||||
void indexIntoPrimitiveShortArray() {
|
||||
short[] shorts = { (short) 33, (short) 44, (short) 55 };
|
||||
|
||||
expression = parser.parseExpression("[2]");
|
||||
|
||||
assertThat(expression.getValue(shorts)).isEqualTo((short) 55);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(shorts)).isEqualTo((short) 55);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("S");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoPrimitiveByteArray() {
|
||||
byte[] bytes = { (byte) 2, (byte) 3, (byte) 4 };
|
||||
|
||||
expression = parser.parseExpression("[2]");
|
||||
|
||||
assertThat(expression.getValue(bytes)).isEqualTo((byte) 4);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(bytes)).isEqualTo((byte) 4);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("B");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoPrimitiveIntArray() {
|
||||
int[] ints = { 8, 9, 10 };
|
||||
|
||||
expression = parser.parseExpression("[2]");
|
||||
|
||||
assertThat(expression.getValue(ints)).isEqualTo(10);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(ints)).isEqualTo(10);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("I");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoPrimitiveLongArray() {
|
||||
long[] longs = { 2L, 3L, 4L };
|
||||
|
||||
expression = parser.parseExpression("[0]");
|
||||
|
||||
assertThat(expression.getValue(longs)).isEqualTo(2L);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(longs)).isEqualTo(2L);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("J");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoPrimitiveFloatArray() {
|
||||
float[] floats = { 6.0f, 7.0f, 8.0f };
|
||||
|
||||
expression = parser.parseExpression("[0]");
|
||||
|
||||
assertThat(expression.getValue(floats)).isEqualTo(6.0f);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(floats)).isEqualTo(6.0f);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("F");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoPrimitiveDoubleArray() {
|
||||
double[] doubles = { 3.0d, 4.0d, 5.0d };
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(expression.getValue(doubles)).isEqualTo(4.0d);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(doubles)).isEqualTo(4.0d);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("D");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoPrimitiveCharArray() {
|
||||
char[] chars = { 'a', 'b', 'c' };
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(expression.getValue(chars)).isEqualTo('b');
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(chars)).isEqualTo('b');
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("C");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoStringArray() {
|
||||
String[] strings = { "a", "b", "c" };
|
||||
|
||||
expression = parser.parseExpression("[0]");
|
||||
|
||||
assertThat(expression.getValue(strings)).isEqualTo("a");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(strings)).isEqualTo("a");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoNumberArray() {
|
||||
Number[] numbers = { 2, 8, 9 };
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(expression.getValue(numbers)).isEqualTo(8);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(numbers)).isEqualTo(8);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Number");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexInto2DPrimitiveIntArray() {
|
||||
int[][] array = new int[][] {
|
||||
{ 1, 2, 3 },
|
||||
{ 4, 5, 6 }
|
||||
};
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("4 5 6");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("4 5 6");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("[I");
|
||||
|
||||
expression = parser.parseExpression("[1][2]");
|
||||
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("6");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("6");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("I");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexInto2DStringArray() {
|
||||
String[][] array = new String[][] {
|
||||
{ "a", "b", "c" },
|
||||
{ "d", "e", "f" }
|
||||
};
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("d e f");
|
||||
assertCanCompile(expression);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("[Ljava/lang/String");
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("d e f");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("[Ljava/lang/String");
|
||||
|
||||
expression = parser.parseExpression("[1][2]");
|
||||
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("f");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("f");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void indexIntoArrayOfListOfString() {
|
||||
List<String>[] array = new List[] {
|
||||
Arrays.asList("a", "b", "c"),
|
||||
Arrays.asList("d", "e", "f")
|
||||
};
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("d e f");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("d e f");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/util/List");
|
||||
|
||||
expression = parser.parseExpression("[1][2]");
|
||||
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("f");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("f");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("unchecked")
|
||||
void indexIntoArrayOfMap() {
|
||||
Map<String, String>[] array = new Map[] { Collections.singletonMap("key", "value1") };
|
||||
|
||||
expression = parser.parseExpression("[0]");
|
||||
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("{key=value1}");
|
||||
assertCanCompile(expression);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/util/Map");
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("{key=value1}");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/util/Map");
|
||||
|
||||
expression = parser.parseExpression("[0]['key']");
|
||||
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("value1");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(array))).isEqualTo("value1");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoListOfString() {
|
||||
List<String> list = Arrays.asList("aaa", "bbb", "ccc");
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(expression.getValue(list)).isEqualTo("bbb");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(list)).isEqualTo("bbb");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoListOfInteger() {
|
||||
List<Integer> list = Arrays.asList(123, 456, 789);
|
||||
|
||||
expression = parser.parseExpression("[2]");
|
||||
|
||||
assertThat(expression.getValue(list)).isEqualTo(789);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(list)).isEqualTo(789);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoListOfStringArray() {
|
||||
List<String[]> list = Arrays.asList(
|
||||
new String[] { "a", "b", "c" },
|
||||
new String[] { "d", "e", "f" }
|
||||
);
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("d e f");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("d e f");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
|
||||
expression = parser.parseExpression("[1][0]");
|
||||
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("d");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("d");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoListOfIntegerArray() {
|
||||
List<Integer[]> list = Arrays.asList(
|
||||
new Integer[] { 1, 2, 3 },
|
||||
new Integer[] { 4, 5, 6 }
|
||||
);
|
||||
|
||||
expression = parser.parseExpression("[0]");
|
||||
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("1 2 3");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("1 2 3");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
|
||||
expression = parser.parseExpression("[0][1]");
|
||||
|
||||
assertThat(expression.getValue(list)).isEqualTo(2);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(list)).isEqualTo(2);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Integer");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoListOfListOfString() {
|
||||
List<List<String>> list = Arrays.asList(
|
||||
Arrays.asList("a", "b", "c"),
|
||||
Arrays.asList("d", "e", "f")
|
||||
);
|
||||
|
||||
expression = parser.parseExpression("[1]");
|
||||
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("d e f");
|
||||
assertCanCompile(expression);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("d e f");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
|
||||
expression = parser.parseExpression("[1][2]");
|
||||
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("f");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(list))).isEqualTo("f");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoMap() {
|
||||
Map<String, Integer> map = Collections.singletonMap("aaa", 111);
|
||||
|
||||
expression = parser.parseExpression("['aaa']");
|
||||
|
||||
assertThat(expression.getValue(map)).isEqualTo(111);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(map)).isEqualTo(111);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoMapOfListOfString() {
|
||||
Map<String, List<String>> map = Collections.singletonMap("foo", Arrays.asList("a", "b", "c"));
|
||||
|
||||
expression = parser.parseExpression("['foo']");
|
||||
|
||||
assertThat(stringify(expression.getValue(map))).isEqualTo("a b c");
|
||||
assertCanCompile(expression);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
assertThat(stringify(expression.getValue(map))).isEqualTo("a b c");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
|
||||
expression = parser.parseExpression("['foo'][2]");
|
||||
|
||||
assertThat(stringify(expression.getValue(map))).isEqualTo("c");
|
||||
assertCanCompile(expression);
|
||||
assertThat(stringify(expression.getValue(map))).isEqualTo("c");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
@Test
|
||||
void indexIntoObject() {
|
||||
TestClass6 tc = new TestClass6();
|
||||
|
||||
// field access
|
||||
expression = parser.parseExpression("['orange']");
|
||||
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value1");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value1");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
|
||||
|
||||
// field access
|
||||
expression = parser.parseExpression("['peach']");
|
||||
|
||||
assertThat(expression.getValue(tc)).isEqualTo(34L);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo(34L);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("J");
|
||||
|
||||
// property access (getter)
|
||||
expression = parser.parseExpression("['banana']");
|
||||
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value3");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(tc)).isEqualTo("value3");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/String");
|
||||
}
|
||||
|
||||
@Test // gh-32694, gh-32908
|
||||
void indexIntoArrayUsingIntegerWrapper() {
|
||||
context.setVariable("array", new int[] {1, 2, 3, 4});
|
||||
context.setVariable("index", 2);
|
||||
|
||||
expression = parser.parseExpression("#array[#index]");
|
||||
|
||||
assertThat(expression.getValue(context)).isEqualTo(3);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(context)).isEqualTo(3);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("I");
|
||||
}
|
||||
|
||||
@Test // gh-32694, gh-32908
|
||||
void indexIntoListUsingIntegerWrapper() {
|
||||
context.setVariable("list", Arrays.asList(1, 2, 3, 4));
|
||||
context.setVariable("index", 2);
|
||||
|
||||
expression = parser.parseExpression("#list[#index]");
|
||||
|
||||
assertThat(expression.getValue(context)).isEqualTo(3);
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(context)).isEqualTo(3);
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
@Test // gh-32903
|
||||
void indexIntoMapUsingPrimitiveLiteral() {
|
||||
Map<Object, String> map = new HashMap<>();
|
||||
map.put(false, "0"); // BooleanLiteral
|
||||
map.put(1, "ABC"); // IntLiteral
|
||||
map.put(2L, "XYZ"); // LongLiteral
|
||||
map.put(9.99F, "~10"); // FloatLiteral
|
||||
map.put(3.14159, "PI"); // RealLiteral
|
||||
context.setVariable("map", map);
|
||||
|
||||
// BooleanLiteral
|
||||
expression = parser.parseExpression("#map[false]");
|
||||
assertThat(expression.getValue(context)).isEqualTo("0");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(context)).isEqualTo("0");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
|
||||
// IntLiteral
|
||||
expression = parser.parseExpression("#map[1]");
|
||||
assertThat(expression.getValue(context)).isEqualTo("ABC");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(context)).isEqualTo("ABC");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
|
||||
// LongLiteral
|
||||
expression = parser.parseExpression("#map[2L]");
|
||||
assertThat(expression.getValue(context)).isEqualTo("XYZ");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(context)).isEqualTo("XYZ");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
|
||||
// FloatLiteral
|
||||
expression = parser.parseExpression("#map[9.99F]");
|
||||
assertThat(expression.getValue(context)).isEqualTo("~10");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(context)).isEqualTo("~10");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
|
||||
// RealLiteral
|
||||
expression = parser.parseExpression("#map[3.14159]");
|
||||
assertThat(expression.getValue(context)).isEqualTo("PI");
|
||||
assertCanCompile(expression);
|
||||
assertThat(expression.getValue(context)).isEqualTo("PI");
|
||||
assertThat(getAst().getExitDescriptor()).isEqualTo("Ljava/lang/Object");
|
||||
}
|
||||
|
||||
private String stringify(Object object) {
|
||||
Stream<? extends Object> stream;
|
||||
if (object instanceof Collection) {
|
||||
stream = ((Collection<?>) object).stream();
|
||||
}
|
||||
else if (object instanceof Object[]) {
|
||||
stream = Arrays.stream((Object[]) object);
|
||||
}
|
||||
else if (object instanceof int[]) {
|
||||
stream = Arrays.stream((int[]) object).mapToObj(Integer::valueOf);
|
||||
}
|
||||
else {
|
||||
return String.valueOf(object);
|
||||
}
|
||||
return stream.map(Object::toString).collect(Collectors.joining(" "));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void typeReference() {
|
||||
expression = parse("T(String)");
|
||||
|
||||
+12
-8
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2020 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.
|
||||
@@ -154,7 +154,7 @@ final class PersistenceUnitReader {
|
||||
/**
|
||||
* Validate the given stream and return a valid DOM document for parsing.
|
||||
*/
|
||||
Document buildDocument(ErrorHandler handler, InputStream stream)
|
||||
protected Document buildDocument(ErrorHandler handler, InputStream stream)
|
||||
throws ParserConfigurationException, SAXException, IOException {
|
||||
|
||||
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
|
||||
@@ -168,7 +168,9 @@ final class PersistenceUnitReader {
|
||||
/**
|
||||
* Parse the validated document and add entries to the given unit info list.
|
||||
*/
|
||||
void parseDocument(Resource resource, Document document, List<SpringPersistenceUnitInfo> infos) throws IOException {
|
||||
protected List<SpringPersistenceUnitInfo> parseDocument(
|
||||
Resource resource, Document document, List<SpringPersistenceUnitInfo> infos) throws IOException {
|
||||
|
||||
Element persistence = document.getDocumentElement();
|
||||
String version = persistence.getAttribute(PERSISTENCE_VERSION);
|
||||
URL rootUrl = determinePersistenceUnitRootUrl(resource);
|
||||
@@ -177,12 +179,14 @@ final class PersistenceUnitReader {
|
||||
for (Element unit : units) {
|
||||
infos.add(parsePersistenceUnitInfo(unit, version, rootUrl));
|
||||
}
|
||||
|
||||
return infos;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the unit info DOM element.
|
||||
*/
|
||||
SpringPersistenceUnitInfo parsePersistenceUnitInfo(
|
||||
protected SpringPersistenceUnitInfo parsePersistenceUnitInfo(
|
||||
Element persistenceUnit, String version, @Nullable URL rootUrl) throws IOException {
|
||||
|
||||
SpringPersistenceUnitInfo unitInfo = new SpringPersistenceUnitInfo();
|
||||
@@ -249,7 +253,7 @@ final class PersistenceUnitReader {
|
||||
/**
|
||||
* Parse the {@code property} XML elements.
|
||||
*/
|
||||
void parseProperties(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
||||
protected void parseProperties(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
||||
Element propRoot = DomUtils.getChildElementByTagName(persistenceUnit, PROPERTIES);
|
||||
if (propRoot == null) {
|
||||
return;
|
||||
@@ -265,7 +269,7 @@ final class PersistenceUnitReader {
|
||||
/**
|
||||
* Parse the {@code class} XML elements.
|
||||
*/
|
||||
void parseManagedClasses(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
||||
protected void parseManagedClasses(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
||||
List<Element> classes = DomUtils.getChildElementsByTagName(persistenceUnit, MANAGED_CLASS_NAME);
|
||||
for (Element element : classes) {
|
||||
String value = DomUtils.getTextValue(element).trim();
|
||||
@@ -278,7 +282,7 @@ final class PersistenceUnitReader {
|
||||
/**
|
||||
* Parse the {@code mapping-file} XML elements.
|
||||
*/
|
||||
void parseMappingFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
||||
protected void parseMappingFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) {
|
||||
List<Element> files = DomUtils.getChildElementsByTagName(persistenceUnit, MAPPING_FILE_NAME);
|
||||
for (Element element : files) {
|
||||
String value = DomUtils.getTextValue(element).trim();
|
||||
@@ -291,7 +295,7 @@ final class PersistenceUnitReader {
|
||||
/**
|
||||
* Parse the {@code jar-file} XML elements.
|
||||
*/
|
||||
void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) throws IOException {
|
||||
protected void parseJarFiles(Element persistenceUnit, SpringPersistenceUnitInfo unitInfo) throws IOException {
|
||||
List<Element> jars = DomUtils.getChildElementsByTagName(persistenceUnit, JAR_FILE_URL);
|
||||
for (Element element : jars) {
|
||||
String value = DomUtils.getTextValue(element).trim();
|
||||
|
||||
+2
-2
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2022 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.
|
||||
@@ -93,7 +93,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractHttpMe
|
||||
|
||||
/**
|
||||
* Sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes}
|
||||
* to {@code text/xml} and {@code application/xml}, and {@code application/*+xml}.
|
||||
* to {@code text/xml} and {@code application/xml}, and {@code application/*-xml}.
|
||||
*/
|
||||
public SourceHttpMessageConverter() {
|
||||
super(MediaType.APPLICATION_XML, MediaType.TEXT_XML, new MediaType("application", "*+xml"));
|
||||
|
||||
Reference in New Issue
Block a user