Add Kotlin support to PreFilter and PostFilter annotations

Closes gh-15093
This commit is contained in:
Blagoja Stamatovski
2024-05-18 15:39:27 +02:00
committed by Josh Cummings
parent fbeb82ef62
commit 63f48167bd
4 changed files with 387 additions and 21 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2022 the original author or authors.
* Copyright 2002-2024 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,6 +52,7 @@ import org.springframework.util.Assert;
*
* @author Luke Taylor
* @author Evgeniy Cheban
* @author Blagoja Stamatovski
* @since 3.0
*/
public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpressionHandler<MethodInvocation>
@@ -109,12 +110,13 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
}
/**
* Filters the {@code filterTarget} object (which must be either a collection, array,
* map or stream), by evaluating the supplied expression.
* Filters the {@code filterTarget} object (which must be either a {@link Collection},
* {@code Array}, {@link Map} or {@link Stream}), by evaluating the supplied
* expression.
* <p>
* If a {@code Collection} or {@code Map} is used, the original instance will be
* modified to contain the elements for which the permission expression evaluates to
* {@code true}. For an array, a new array instance will be returned.
* Returns new instances of the same type as the supplied {@code filterTarget} object
* @return The filtered {@link Collection}, {@code Array}, {@link Map} or
* {@link Stream}
*/
@Override
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) {
@@ -151,9 +153,17 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
}
}
this.logger.debug(LogMessage.format("Retaining elements: %s", retain));
filterTarget.clear();
filterTarget.addAll(retain);
return filterTarget;
try {
filterTarget.clear();
filterTarget.addAll(retain);
return filterTarget;
}
catch (UnsupportedOperationException unsupportedOperationException) {
this.logger.debug(LogMessage.format(
"Collection threw exception: %s. Will return a new instance instead of mutating its state.",
unsupportedOperationException.getMessage()));
return retain;
}
}
private Object filterArray(Object[] filterTarget, Expression filterExpression, EvaluationContext ctx,
@@ -178,7 +188,7 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
return filtered;
}
private <K, V> Object filterMap(final Map<K, V> filterTarget, Expression filterExpression, EvaluationContext ctx,
private <K, V> Object filterMap(Map<K, V> filterTarget, Expression filterExpression, EvaluationContext ctx,
MethodSecurityExpressionOperations rootObject) {
Map<K, V> retain = new LinkedHashMap<>(filterTarget.size());
this.logger.debug(LogMessage.format("Filtering map with %s elements", filterTarget.size()));
@@ -189,9 +199,17 @@ public class DefaultMethodSecurityExpressionHandler extends AbstractSecurityExpr
}
}
this.logger.debug(LogMessage.format("Retaining elements: %s", retain));
filterTarget.clear();
filterTarget.putAll(retain);
return filterTarget;
try {
filterTarget.clear();
filterTarget.putAll(retain);
return filterTarget;
}
catch (UnsupportedOperationException unsupportedOperationException) {
this.logger.debug(LogMessage.format(
"Map threw exception: %s. Will return a new instance instead of mutating its state.",
unsupportedOperationException.getMessage()));
return retain;
}
}
private Object filterStream(final Stream<?> filterTarget, Expression filterExpression, EvaluationContext ctx,