|
1 | 1 | /*
|
2 |
| - * Copyright 2002-2023 the original author or authors. |
| 2 | + * Copyright 2002-2024 the original author or authors. |
3 | 3 | *
|
4 | 4 | * Licensed under the Apache License, Version 2.0 (the "License");
|
5 | 5 | * you may not use this file except in compliance with the License.
|
|
28 | 28 |
|
29 | 29 | import org.junit.jupiter.api.Test;
|
30 | 30 |
|
| 31 | +import org.springframework.beans.factory.BeanCreationException; |
31 | 32 | import org.springframework.beans.factory.ObjectFactory;
|
32 | 33 | import org.springframework.beans.factory.annotation.Autowired;
|
33 | 34 | import org.springframework.beans.factory.annotation.Qualifier;
|
|
42 | 43 | import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
43 | 44 | import org.springframework.context.annotation.AnnotationConfigUtils;
|
44 | 45 | import org.springframework.context.support.GenericApplicationContext;
|
| 46 | +import org.springframework.core.SpringProperties; |
45 | 47 | import org.springframework.core.convert.support.DefaultConversionService;
|
46 | 48 | import org.springframework.core.convert.support.GenericConversionService;
|
47 | 49 | import org.springframework.core.io.ClassPathResource;
|
48 | 50 | import org.springframework.core.io.Resource;
|
49 | 51 | import org.springframework.core.io.support.EncodedResource;
|
50 | 52 | import org.springframework.core.testfixture.io.SerializationTestUtils;
|
| 53 | +import org.springframework.expression.spel.SpelEvaluationException; |
51 | 54 | import org.springframework.util.FileCopyUtils;
|
52 | 55 |
|
53 | 56 | import static org.assertj.core.api.Assertions.assertThat;
|
| 57 | +import static org.assertj.core.api.Assertions.assertThatExceptionOfType; |
| 58 | +import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException; |
| 59 | +import static org.springframework.context.expression.StandardBeanExpressionResolver.MAX_SPEL_EXPRESSION_LENGTH_PROPERTY_NAME; |
54 | 60 |
|
55 | 61 | /**
|
| 62 | + * Integration tests for SpEL expression support in an {@code ApplicationContext}. |
| 63 | + * |
56 | 64 | * @author Juergen Hoeller
|
57 | 65 | * @author Sam Brannen
|
58 | 66 | * @since 3.0
|
@@ -268,6 +276,70 @@ void resourceInjection() throws IOException {
|
268 | 276 | }
|
269 | 277 | }
|
270 | 278 |
|
| 279 | + @Test |
| 280 | + void maxSpelExpressionLengthMustBeAnInteger() { |
| 281 | + doWithMaxSpelExpressionLength("boom", () -> { |
| 282 | + try (AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext()) { |
| 283 | + assertThatIllegalArgumentException() |
| 284 | + .isThrownBy(ac::refresh) |
| 285 | + .withMessageStartingWith("Failed to parse value for system property [%s]", |
| 286 | + MAX_SPEL_EXPRESSION_LENGTH_PROPERTY_NAME) |
| 287 | + .withMessageContaining("boom"); |
| 288 | + } |
| 289 | + }); |
| 290 | + } |
| 291 | + |
| 292 | + @Test |
| 293 | + void maxSpelExpressionLengthMustBePositive() { |
| 294 | + doWithMaxSpelExpressionLength("-99", () -> { |
| 295 | + try (AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext()) { |
| 296 | + assertThatIllegalArgumentException() |
| 297 | + .isThrownBy(ac::refresh) |
| 298 | + .withMessage("Value [%d] for system property [%s] must be positive", -99, |
| 299 | + MAX_SPEL_EXPRESSION_LENGTH_PROPERTY_NAME); |
| 300 | + } |
| 301 | + }); |
| 302 | + } |
| 303 | + |
| 304 | + @Test |
| 305 | + void maxSpelExpressionLength() { |
| 306 | + final String expression = "#{ 'xyz' + 'xyz' + 'xyz' }"; |
| 307 | + |
| 308 | + // With the default max length of 10_000, the expression should succeed. |
| 309 | + evaluateExpressionInBean(expression); |
| 310 | + |
| 311 | + // With a max length of 20, the expression should fail. |
| 312 | + doWithMaxSpelExpressionLength("20", () -> |
| 313 | + assertThatExceptionOfType(BeanCreationException.class) |
| 314 | + .isThrownBy(() -> evaluateExpressionInBean(expression)) |
| 315 | + .havingRootCause() |
| 316 | + .isInstanceOf(SpelEvaluationException.class) |
| 317 | + .withMessageEndingWith("exceeding the threshold of '20' characters")); |
| 318 | + } |
| 319 | + |
| 320 | + private static void doWithMaxSpelExpressionLength(String maxLength, Runnable action) { |
| 321 | + try { |
| 322 | + SpringProperties.setProperty(MAX_SPEL_EXPRESSION_LENGTH_PROPERTY_NAME, maxLength); |
| 323 | + action.run(); |
| 324 | + } |
| 325 | + finally { |
| 326 | + SpringProperties.setProperty(MAX_SPEL_EXPRESSION_LENGTH_PROPERTY_NAME, null); |
| 327 | + } |
| 328 | + } |
| 329 | + |
| 330 | + private static void evaluateExpressionInBean(String expression) { |
| 331 | + try (AnnotationConfigApplicationContext ac = new AnnotationConfigApplicationContext()) { |
| 332 | + GenericBeanDefinition bd = new GenericBeanDefinition(); |
| 333 | + bd.setBeanClass(String.class); |
| 334 | + bd.getConstructorArgumentValues().addGenericArgumentValue(expression); |
| 335 | + ac.registerBeanDefinition("str", bd); |
| 336 | + ac.refresh(); |
| 337 | + |
| 338 | + String str = ac.getBean("str", String.class); |
| 339 | + assertThat(str).isEqualTo("xyz".repeat(3)); // "#{ 'xyz' + 'xyz' + 'xyz' }" |
| 340 | + } |
| 341 | + } |
| 342 | + |
271 | 343 |
|
272 | 344 | @SuppressWarnings("serial")
|
273 | 345 | public static class ValueTestBean implements Serializable {
|
|
0 commit comments