core/src/main/java/org/springframework/security/access/expression/method/DefaultMethodSecurityExpressionHandler.java
@SuppressWarnings("unchecked")
	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 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;
		}

		if (filterTarget instanceof Stream) {
			final Stream<?> original = (Stream<?>) filterTarget;

			return original.filter(filterObject -> {
				rootObject.setFilterObject(filterObject);
				return ExpressionUtils.evaluateAsBoolean(filterExpression, ctx);
			})
					.onClose(original::close);
		}

		throw new IllegalArgumentException(
				"Filter target must be a collection, array, or stream type, but was "
						+ filterTarget);
	}
@SuppressWarnings("unchecked")
	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 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;
		}

		if (filterTarget instanceof Stream) {
			final Stream<?> original = (Stream<?>) filterTarget;

			return original.filter(filterObject -> {
				rootObject.setFilterObject(filterObject);
				return ExpressionUtils.evaluateAsBoolean(filterExpression, ctx);
			})
					.onClose(original::close);
		}

		throw new IllegalArgumentException(
				"Filter target must be a collection, array, or stream type, but was "
						+ filterTarget);
	}
@ SuppressWarnings ( "unchecked" ) 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 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 ; } if ( filterTarget instanceof Stream ) { final Stream < ? > original = ( Stream < ? > ) filterTarget ; return original . filter ( filterObject -> { rootObject . setFilterObject ( filterObject ) ; return ExpressionUtils . evaluateAsBoolean ( filterExpression , ctx ) ; } ) . onClose ( original :: close ) ; } throw new IllegalArgumentException ( "Filter target must be a collection, array, or stream type, but was " + filterTarget ) ; }
Filters the {@code filterTarget} object (which must be either a collection, array,
or stream), 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.
Filters the {