Created
September 4, 2013 08:20
-
-
Save gytisgreitai/6434201 to your computer and use it in GitHub Desktop.
DefaultMethodSecurityExpressionHandler with support for java.lang.Iterable
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package org.example.security; | |
import java.lang.reflect.Array; | |
import java.util.*; | |
import org.springframework.expression.EvaluationContext; | |
import org.springframework.expression.Expression; | |
import org.springframework.security.access.PermissionCacheOptimizer; | |
import org.springframework.security.access.expression.ExpressionUtils; | |
import org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler; | |
import org.springframework.security.access.expression.method.MethodSecurityExpressionOperations; | |
/** | |
* Extension of {@link DefaultMethodSecurityExpressionHandler} to support {@link Iterable} | |
* | |
*/ | |
public class CustomMethodSecurityExpressionHandler extends DefaultMethodSecurityExpressionHandler { | |
private PermissionCacheOptimizer permissionCacheOptimizer; | |
/** | |
* Filters the {@code filterTarget} object (which must be either a collection or an array), by evaluating the | |
* supplied expression. | |
* <p/> | |
* If a {@code Collection} 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. And for Iterable same object | |
* will be modified. | |
*/ | |
@SuppressWarnings("unchecked") | |
@Override | |
public Object filter(Object filterTarget, Expression filterExpression, EvaluationContext ctx) { | |
MethodSecurityExpressionOperations rootObject = (MethodSecurityExpressionOperations) ctx.getRootObject().getValue(); | |
final boolean debug = logger.isDebugEnabled(); | |
List retainList; | |
if (debug) { | |
logger.debug("Filtering with expression: " + filterExpression.getExpressionString()); | |
} | |
if (filterTarget instanceof Iterable) { | |
Iterable iterable = (Iterable) filterTarget; | |
if (debug) { | |
logger.debug("Filtering iterable " + iterable); | |
} | |
// Not quite sure how to handle this? First create collection from iterable? | |
// if (permissionCacheOptimizer != null) { | |
// permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), iterable); | |
// } | |
Iterator iterator = iterable.iterator(); | |
while (iterator.hasNext()) { | |
Object filterObject = iterator.next(); | |
rootObject.setFilterObject(filterObject); | |
if (!ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) { | |
iterator.remove(); | |
} | |
} | |
if (debug) { | |
logger.debug("Retaining elements: " + iterator); | |
} | |
return filterTarget; | |
} | |
if (filterTarget instanceof Collection) { | |
Collection collection = (Collection) filterTarget; | |
retainList = new ArrayList(collection.size()); | |
if (debug) { | |
logger.debug("Filtering collection with " + collection.size() + " elements"); | |
} | |
if (permissionCacheOptimizer != null) { | |
permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), collection); | |
} | |
for (Object filterObject : (Collection) filterTarget) { | |
rootObject.setFilterObject(filterObject); | |
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) { | |
retainList.add(filterObject); | |
} | |
} | |
if (debug) { | |
logger.debug("Retaining elements: " + retainList); | |
} | |
collection.clear(); | |
collection.addAll(retainList); | |
return filterTarget; | |
} | |
if (filterTarget.getClass().isArray()) { | |
Object[] array = (Object[]) filterTarget; | |
retainList = new ArrayList(array.length); | |
if (debug) { | |
logger.debug("Filtering array with " + array.length + " elements"); | |
} | |
if (permissionCacheOptimizer != null) { | |
permissionCacheOptimizer.cachePermissionsFor(rootObject.getAuthentication(), Arrays.asList(array)); | |
} | |
for (Object o : array) { | |
rootObject.setFilterObject(o); | |
if (ExpressionUtils.evaluateAsBoolean(filterExpression, ctx)) { | |
retainList.add(o); | |
} | |
} | |
if (debug) { | |
logger.debug("Retaining elements: " + retainList); | |
} | |
Object[] filtered = (Object[]) Array.newInstance(filterTarget.getClass().getComponentType(), | |
retainList.size()); | |
for (int i = 0; i < retainList.size(); i++) { | |
filtered[i] = retainList.get(i); | |
} | |
return filtered; | |
} | |
throw new IllegalArgumentException("Filter target must be a collection, iterable or array type, but was " + filterTarget); | |
} | |
public void setPermissionCacheOptimizer(PermissionCacheOptimizer permissionCacheOptimizer) { | |
this.permissionCacheOptimizer = permissionCacheOptimizer; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment