[spring-extensions] branch maint-5 updated: IDP-1314 Add SpringExpressionFunction (and tests)
Rod Widdowson
rdw at steadingsoftware.com
Tue Jul 10 11:47:42 EDT 2018
This is an automated email from the git hooks/post-receive script.
rdw pushed a commit to branch maint-5
in repository spring-extensions.
View the commit online:
http://git.shibboleth.net/view/?p=spring-extensions.git;a=commit;h=104828c10779178c0b2669e40d4a4b633916bd9b
The following commit(s) were added to refs/heads/maint-5 by this push:
new 104828c IDP-1314 Add SpringExpressionFunction (and tests)
104828c is described below
commit 104828c10779178c0b2669e40d4a4b633916bd9b
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Tue Jul 10 10:13:05 2018 +0100
IDP-1314 Add SpringExpressionFunction (and tests)
https://issues.shibboleth.net/jira/browse/IDP-1314
---
...java => AbstractSpringExpressionEvaluator.java} | 93 ++++++++++++++++++----
.../ext/spring/util/SpringExpressionFunction.java | 53 ++++++++++++
.../ext/spring/util/SpringExpressionPredicate.java | 82 ++-----------------
.../ext/spring/util/SpringExpressionTest.java | 57 +++++++++++++
4 files changed, 195 insertions(+), 90 deletions(-)
diff --git a/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionPredicate.java b/src/main/java/net/shibboleth/ext/spring/util/AbstractSpringExpressionEvaluator.java
similarity index 59%
copy from src/main/java/net/shibboleth/ext/spring/util/SpringExpressionPredicate.java
copy to src/main/java/net/shibboleth/ext/spring/util/AbstractSpringExpressionEvaluator.java
index 769d97d..dfb9a3c 100644
--- a/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionPredicate.java
+++ b/src/main/java/net/shibboleth/ext/spring/util/AbstractSpringExpressionEvaluator.java
@@ -34,42 +34,85 @@ import org.springframework.expression.ParseException;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
-import com.google.common.base.Predicate;
-
/**
- * Predicate whose condition is defined by an Spring EL expression.
+ * A component that evaluates a Spring EL expression against a set of inputs
+ * and returns the result.
*
* @param <T> type of input
+ * @param <U> type of output
*
* @since 5.4.0
*/
-public class SpringExpressionPredicate<T> implements Predicate<T> {
+public abstract class AbstractSpringExpressionEvaluator<T, U> {
/** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(SpringExpressionPredicate.class);
+ @Nonnull private final Logger log = LoggerFactory.getLogger(AbstractSpringExpressionEvaluator.class);
/** SpEL expression to evaluate. */
@Nullable private String springExpression;
/** A custom object to inject into the expression context. */
@Nullable private Object customObject;
+
+ /** The output type. */
+ @Nullable private Class<U> outputType;
+
+ /** The input type. */
+ @Nullable private Class<T> inputType;
+
/** Whether to raise runtime exceptions if expression fails. */
private boolean hideExceptions;
/** Value to return from predicate when an error occurs. */
- private boolean returnOnError;
+ private U returnOnError;
/**
* Constructor.
*
* @param expression the expression to evaluate
*/
- public SpringExpressionPredicate(@Nonnull @NotEmpty @ParameterName(name="expression") final String expression) {
+ public AbstractSpringExpressionEvaluator(
+ final @Nonnull @NotEmpty @ParameterName(name="expression") String expression) {
springExpression = Constraint.isNotNull(StringSupport.trimOrNull(expression),
"Expression cannot be null or empty");
}
+
+ /**
+ * Set the output type to be enforced.
+ *
+ * @param type output type
+ */
+ public void setOutputType(@Nullable final Class type) {
+ outputType = type;
+ }
+ /**
+ * Get the output type to be enforced.
+ *
+ * @return output type
+ */
+ @Nullable protected Class<U> getOutputType() {
+ return outputType;
+ }
+
+ /**
+ * Get the input type to be enforced.
+ *
+ * @return input type
+ */
+ @Nullable public Class<T> getInputType() {
+ return inputType;
+ }
+
+ /**
+ * Set the input type to be enforced.
+ *
+ * @param type input type
+ */
+ public void setInputType(@Nullable final Class<T> type) {
+ inputType = type;
+ }
/**
* Set a custom (externally provided) object.
@@ -81,6 +124,16 @@ public class SpringExpressionPredicate<T> implements Predicate<T> {
}
/**
+ * Get the custom (externally provided) object.
+ *
+ * @return the custom object
+ */
+ public Object getCustomObject() {
+ return customObject;
+ }
+
+
+ /**
* Set whether to hide exceptions in expression execution (default is false).
*
* @param flag flag to set
@@ -92,15 +145,21 @@ public class SpringExpressionPredicate<T> implements Predicate<T> {
/**
* Set value to return if an error occurs (default is false).
*
- * @param flag flag to set
+ * @param what value to set
*/
- public void setReturnOnError(final boolean flag) {
- returnOnError = flag;
+ public void setReturnOnError(final U what) {
+ returnOnError = what;
}
/** {@inheritDoc} */
- @Override
- public boolean apply(@Nullable final T input) {
+ protected U evaluate(@Nullable final T input) {
+
+ // Try outside the try so as to preserve derived semantics
+ if (null != input && null != getInputType() && !getInputType().isInstance(input)) {
+ log.error("Input was type {} which is not an instance of {}", input.getClass(), getInputType());
+ throw new ClassCastException("Input was type " + input.getClass() + " which is not an instance of "
+ + getInputType());
+ }
try {
final ExpressionParser parser = new SpelExpressionParser();
@@ -108,7 +167,13 @@ public class SpringExpressionPredicate<T> implements Predicate<T> {
context.setVariable("custom", customObject);
context.setVariable("input", input);
prepareContext(context, input);
- return parser.parseExpression(springExpression).getValue(context, Boolean.class);
+ final Object output = parser.parseExpression(springExpression).getValue(context);
+
+ if (null != getOutputType() && null != output && !getOutputType().isInstance(output)) {
+ log.error("Output of type {} was not of type {}", output.getClass(), getOutputType());
+ return returnOnError;
+ }
+ return (U) output;
} catch (final ParseException|EvaluationException e) {
log.error("Error evaluating Spring expression", e);
if (hideExceptions) {
@@ -124,7 +189,7 @@ public class SpringExpressionPredicate<T> implements Predicate<T> {
* @param context expression context
* @param input to predicate
*/
- protected void prepareContext(@Nonnull final EvaluationContext context, @Nullable final T input) {
+ protected void prepareContext(@Nonnull final EvaluationContext context, @Nullable final T input) {
}
diff --git a/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionFunction.java b/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionFunction.java
new file mode 100644
index 0000000..1199888
--- /dev/null
+++ b/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionFunction.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.ext.spring.util;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
+import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+
+import com.google.common.base.Function;
+
+/**
+ * Function whose output is defined by an Spring EL expression.
+ *
+ * @param <T> type of input
+ * @param <U> type of output
+ *
+ * @since 5.4.0
+ */
+public class SpringExpressionFunction<T,U> extends AbstractSpringExpressionEvaluator<T, U>
+ implements Function<T,U> {
+
+ /**
+ * Constructor.
+ *
+ * @param expression the expression to evaluate
+ */
+ public SpringExpressionFunction(@Nonnull @NotEmpty @ParameterName(name="expression") final String expression) {
+ super(expression);
+ }
+
+ /** {@inheritDoc} */
+ @Override
+ public U apply(@Nullable final T input) {
+ return evaluate(input);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionPredicate.java b/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionPredicate.java
index 769d97d..500127c 100644
--- a/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionPredicate.java
+++ b/src/main/java/net/shibboleth/ext/spring/util/SpringExpressionPredicate.java
@@ -22,18 +22,6 @@ import javax.annotation.Nullable;
import net.shibboleth.utilities.java.support.annotation.ParameterName;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
-import net.shibboleth.utilities.java.support.logic.Constraint;
-import net.shibboleth.utilities.java.support.primitive.StringSupport;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.expression.EvaluationContext;
-import org.springframework.expression.EvaluationException;
-import org.springframework.expression.ExpressionParser;
-import org.springframework.expression.ParseException;
-import org.springframework.expression.spel.standard.SpelExpressionParser;
-import org.springframework.expression.spel.support.StandardEvaluationContext;
-
import com.google.common.base.Predicate;
/**
@@ -43,50 +31,17 @@ import com.google.common.base.Predicate;
*
* @since 5.4.0
*/
-public class SpringExpressionPredicate<T> implements Predicate<T> {
-
- /** Class logger. */
- @Nonnull private final Logger log = LoggerFactory.getLogger(SpringExpressionPredicate.class);
-
- /** SpEL expression to evaluate. */
- @Nullable private String springExpression;
+public class SpringExpressionPredicate<T> extends AbstractSpringExpressionEvaluator<T, Boolean>
+ implements Predicate<T> {
- /** A custom object to inject into the expression context. */
- @Nullable private Object customObject;
-
- /** Whether to raise runtime exceptions if expression fails. */
- private boolean hideExceptions;
-
- /** Value to return from predicate when an error occurs. */
- private boolean returnOnError;
-
/**
* Constructor.
*
* @param expression the expression to evaluate
*/
public SpringExpressionPredicate(@Nonnull @NotEmpty @ParameterName(name="expression") final String expression) {
- springExpression = Constraint.isNotNull(StringSupport.trimOrNull(expression),
- "Expression cannot be null or empty");
- }
-
-
- /**
- * Set a custom (externally provided) object.
- *
- * @param object the custom object
- */
- public void setCustomObject(@Nullable final Object object) {
- customObject = object;
- }
-
- /**
- * Set whether to hide exceptions in expression execution (default is false).
- *
- * @param flag flag to set
- */
- public void setHideExceptions(final boolean flag) {
- hideExceptions = flag;
+ super(expression);
+ setOutputType(Boolean.class);
}
/**
@@ -95,37 +50,12 @@ public class SpringExpressionPredicate<T> implements Predicate<T> {
* @param flag flag to set
*/
public void setReturnOnError(final boolean flag) {
- returnOnError = flag;
+ super.setReturnOnError(flag);
}
/** {@inheritDoc} */
@Override
public boolean apply(@Nullable final T input) {
-
- try {
- final ExpressionParser parser = new SpelExpressionParser();
- final StandardEvaluationContext context = new StandardEvaluationContext();
- context.setVariable("custom", customObject);
- context.setVariable("input", input);
- prepareContext(context, input);
- return parser.parseExpression(springExpression).getValue(context, Boolean.class);
- } catch (final ParseException|EvaluationException e) {
- log.error("Error evaluating Spring expression", e);
- if (hideExceptions) {
- return returnOnError;
- }
- throw e;
- }
+ return evaluate(input);
}
-
- /**
- * Decorate the expression context with any additional content.
- *
- * @param context expression context
- * @param input to predicate
- */
- protected void prepareContext(@Nonnull final EvaluationContext context, @Nullable final T input) {
-
- }
-
}
\ No newline at end of file
diff --git a/src/test/java/net/shibboleth/ext/spring/util/SpringExpressionTest.java b/src/test/java/net/shibboleth/ext/spring/util/SpringExpressionTest.java
new file mode 100644
index 0000000..9a0c608
--- /dev/null
+++ b/src/test/java/net/shibboleth/ext/spring/util/SpringExpressionTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the University Corporation for Advanced Internet Development,
+ * Inc. (UCAID) under one or more contributor license agreements. See the
+ * NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The UCAID licenses this file to You under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package net.shibboleth.ext.spring.util;
+
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+/**
+ * Test for the {@link SpringExpressionPredicate} and {@link SpringExpressionFunction}.
+ */
+public class SpringExpressionTest {
+
+ /** Helper function to use this as the bean to test.
+ * @return 99
+ */
+ public int getValue99() {
+ return 99;
+ }
+
+ @Test public void testPredicates() {
+
+ SpringExpressionPredicate predicate = new SpringExpressionPredicate<>("#input.getValue99() == 99");
+
+ Assert.assertTrue(predicate.apply(this));
+
+ predicate = new SpringExpressionPredicate<>("#input.getValue99() == #custom");
+ predicate.setCustomObject(99);
+ Assert.assertTrue(predicate.apply(this));
+
+ }
+
+ @Test public void testFunction() {
+
+ SpringExpressionFunction<Object, SpringExpressionTest> func = new SpringExpressionFunction<>("#input");
+ Assert.assertNull(func.apply(null));
+
+ Assert.assertEquals(func.apply(this), this);
+
+ Assert.assertEquals((int) new SpringExpressionFunction<SpringExpressionTest, Integer>("#input.getValue99()").apply(this), 99);
+
+ }
+}
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list