[java-support] 02/11: JSPT-96 Deprecate all parameterized constructors to EvaluableScript
Rod Widdowson
rdw at steadingsoftware.com
Mon May 4 14:38:20 UTC 2020
This is an automated email from the git hooks/post-receive script.
rdw pushed a commit to branch dev/JSPT-95
in repository java-support.
View the commit online:
http://git.shibboleth.net/view/?p=java-support.git;a=commit;h=1e5e2b0d10fc46955f7dde7fb6151ed7663af66c
commit 1e5e2b0d10fc46955f7dde7fb6151ed7663af66c
Author: Rod Widdowson <rdw at steadingsoftware.com>
AuthorDate: Sat Mar 28 15:44:10 2020 +0000
JSPT-96 Deprecate all parameterized constructors to EvaluableScript
https://issues.shibboleth.net/jira/browse/JSPT-96
---
.../java/support/scripting/EvaluableScript.java | 193 ++++++++++++++++++---
.../support/scripting/EvaluableScriptTest.java | 160 ++++++++++++++++-
2 files changed, 328 insertions(+), 25 deletions(-)
diff --git a/src/main/java/net/shibboleth/utilities/java/support/scripting/EvaluableScript.java b/src/main/java/net/shibboleth/utilities/java/support/scripting/EvaluableScript.java
index 53bc4ce..d12a433 100644
--- a/src/main/java/net/shibboleth/utilities/java/support/scripting/EvaluableScript.java
+++ b/src/main/java/net/shibboleth/utilities/java/support/scripting/EvaluableScript.java
@@ -33,21 +33,28 @@ import javax.script.ScriptEngineManager;
import javax.script.ScriptException;
import net.shibboleth.utilities.java.support.annotation.ParameterName;
+import net.shibboleth.utilities.java.support.annotation.constraint.NonnullAfterInit;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.AbstractInitializableComponent;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
+import net.shibboleth.utilities.java.support.component.ComponentSupport;
import net.shibboleth.utilities.java.support.logic.Constraint;
+import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
+import net.shibboleth.utilities.java.support.primitive.DeprecationSupport;
import net.shibboleth.utilities.java.support.primitive.StringSupport;
+import net.shibboleth.utilities.java.support.primitive.DeprecationSupport.ObjectType;
import net.shibboleth.utilities.java.support.resource.Resource;
import com.google.common.io.Files;
/** This is a helper class that takes care of reading in, optionally compiling, and evaluating a script. */
-public final class EvaluableScript {
+public final class EvaluableScript extends AbstractInitializableComponent {
/** The scripting language. */
- @Nonnull @NotEmpty private final String scriptLanguage;
+ @Nonnull @NotEmpty private String scriptLanguage = "javascript";
/** The script to execute. */
- @Nonnull @NotEmpty private final String script;
+ @NonnullAfterInit @NotEmpty private String script;
/** The script engine to execute the script. */
@Nullable private ScriptEngine scriptEngine;
@@ -56,31 +63,41 @@ public final class EvaluableScript {
@Nullable private CompiledScript compiledScript;
/**
+ * Constructor.
+ */
+ public EvaluableScript() {
+ }
+
+ /**
* Constructor.
*
* @param engineName the JSR-223 scripting engine name
* @param scriptSource the script source
- *
+ * @deprecated in 8.1
* @throws ScriptException thrown if the scripting engine supports compilation and the script does not compile
*/
+ @Deprecated(forRemoval = true, since = "8.1.0")
public EvaluableScript(@ParameterName(name="engineName") @Nonnull @NotEmpty final String engineName,
@ParameterName(name="scriptSource") @Nonnull @NotEmpty final String scriptSource)
throws ScriptException {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "EvaluableScript(parameters...)",
+ null, "by using the setters");
scriptLanguage =
Constraint.isNotNull(StringSupport.trimOrNull(engineName),
"Scripting language can not be null or empty");
script = Constraint.isNotNull(StringSupport.trimOrNull(scriptSource), "Script source can not be null or empty");
- initialize();
+ initializeWithScriptException();
}
/**
* Constructor.
*
* @param scriptSource the script source
- *
+ * @deprecated in 8.1
* @throws ScriptException thrown if the scripting engine supports compilation and the script does not compile
*/
+ @Deprecated(forRemoval = true, since = "8.1.0")
public EvaluableScript(@ParameterName(name="scriptSource") @Nonnull @NotEmpty final String scriptSource)
throws ScriptException {
this("javascript", scriptSource);
@@ -91,15 +108,18 @@ public final class EvaluableScript {
*
* @param engineName the JSR-223 scripting engine name
* @param scriptSource the script source
- *
+ * @deprecated in 8.1
* @throws ScriptException thrown if the script source file can not be read or the scripting engine supports
* compilation and the script does not compile
*
* @since 8.0.0
*/
+ @Deprecated(forRemoval = true, since = "8.1.0")
public EvaluableScript(@ParameterName(name="engineName") @Nonnull @NotEmpty final String engineName,
@ParameterName(name="scriptSource") @Nonnull final Resource scriptSource)
throws ScriptException {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "EvaluableScript(parameters...)",
+ null, "by using the setters");
scriptLanguage = Constraint.isNotNull(StringSupport.trimOrNull(engineName),
"Scripting language can not be null or empty");
@@ -110,7 +130,7 @@ public final class EvaluableScript {
throw new ScriptException(e);
}
- initialize();
+ initializeWithScriptException();
}
/**
@@ -120,9 +140,10 @@ public final class EvaluableScript {
*
* @throws ScriptException thrown if the script source file can not be read or the scripting engine supports
* compilation and the script does not compile
- *
+ * @deprecated in 8.1
* @since 8.0.0
*/
+ @Deprecated(forRemoval = true, since = "8.1.0")
public EvaluableScript(@ParameterName(name="scriptSource") @Nonnull final Resource scriptSource)
throws ScriptException {
this("javascript", scriptSource);
@@ -133,13 +154,16 @@ public final class EvaluableScript {
*
* @param engineName the JSR-223 scripting engine name
* @param scriptSource the script source
- *
+ * @deprecated in 8.1
* @throws ScriptException thrown if the script source file can not be read or the scripting engine supports
* compilation and the script does not compile
*/
+ @Deprecated(forRemoval = true, since = "8.1.0")
public EvaluableScript(@ParameterName(name="engineName") @Nonnull @NotEmpty final String engineName,
@ParameterName(name="scriptSource") @Nonnull final InputStream scriptSource)
throws ScriptException {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "EvaluableScript(parameters...)",
+ null, "by using the setters");
scriptLanguage =
Constraint.isNotNull(StringSupport.trimOrNull(engineName),
"Scripting language can not be null or empty");
@@ -150,7 +174,7 @@ public final class EvaluableScript {
throw new ScriptException(e);
}
- initialize();
+ initializeWithScriptException();
}
/**
@@ -160,9 +184,10 @@ public final class EvaluableScript {
*
* @throws ScriptException thrown if the script source file can not be read or the scripting engine supports
* compilation and the script does not compile
- *
+ * @deprecated in 8.1
* @since 8.0.0
*/
+ @Deprecated(forRemoval = true, since = "8.1.0")
public EvaluableScript(@ParameterName(name="scriptSource") @Nonnull final InputStream scriptSource)
throws ScriptException {
this("javascript", scriptSource);
@@ -173,13 +198,16 @@ public final class EvaluableScript {
*
* @param engineName the JSR-223 scripting engine name
* @param scriptSource the script source
- *
+ * @deprecated in 8.1
* @throws ScriptException thrown if the script source file can not be read or the scripting engine supports
* compilation and the script does not compile
*/
+ @Deprecated(forRemoval = true, since = "8.1.0")
public EvaluableScript(@ParameterName(name="engineName") @Nonnull @NotEmpty final String engineName,
@ParameterName(name="scriptSource") @Nonnull final File scriptSource)
throws ScriptException {
+ DeprecationSupport.warnOnce(ObjectType.METHOD, "EvaluableScript(parameters...)",
+ null, "by using the setters");
scriptLanguage =
Constraint.isNotNull(StringSupport.trimOrNull(engineName),
"Scripting language can not be null or empty");
@@ -204,7 +232,7 @@ public final class EvaluableScript {
throw new ScriptException("Unable to read data from source file " + scriptSource.getAbsolutePath());
}
- initialize();
+ initializeWithScriptException();
}
/**
@@ -214,9 +242,10 @@ public final class EvaluableScript {
*
* @throws ScriptException thrown if the script source file can not be read or the scripting engine supports
* compilation and the script does not compile
- *
+ * @deprecated in 8.1
* @since 8.0.0
*/
+ @Deprecated(forRemoval = true, since = "8.1.0")
public EvaluableScript(@ParameterName(name="scriptSource") @Nonnull final File scriptSource)
throws ScriptException {
this("javascript", scriptSource);
@@ -232,14 +261,87 @@ public final class EvaluableScript {
}
/**
- * Gets the script language.
+ * Sets the script source.
+ *
+ * @param what the script source
+ */
+ @Nonnull @NotEmpty public void setScript(@Nonnull @NotEmpty final String what) {
+ script = Constraint.isNotNull(StringSupport.trimOrNull(what), "Script must not be null");
+ if ("".equals(script)) {
+ throw new ConstraintViolationException("Script must be non-empty");
+ }
+ }
+
+ /**
+ * Sets the script source.
+ *
+ * @param scriptSource how to get the script source
+ * @throws IOException if there were issues reading the script
+ */
+ @Nonnull @NotEmpty public void setScript(@Nonnull final InputStream scriptSource) throws IOException {
+
+ Constraint.isNotNull(scriptSource, "Script source should not be null");
+
+ script = StringSupport.inputStreamToString(
+ Constraint.isNotNull(scriptSource, "Script source can not be null or empty"), null);
+ }
+
+ /**
+ * Sets the script source.
*
- * @return the script source
+ * @param scriptSource how to get the script source
+ * @throws IOException if there were issues reading the script
+ */
+ @Nonnull @NotEmpty public void setScript(@Nonnull final File scriptSource) throws IOException {
+
+ Constraint.isNotNull(scriptSource, "Script source should not be null");
+
+ if (!scriptSource.exists()) {
+ throw new IOException("Script source file " + scriptSource.getAbsolutePath() + " does not exist");
+ }
+
+ if (!scriptSource.canRead()) {
+ throw new IOException("Script source file " + scriptSource.getAbsolutePath()
+ + " exists but is not readable");
+ }
+
+ script = Constraint.isNotNull(
+ StringSupport.trimOrNull(Files.asCharSource(scriptSource, Charset.defaultCharset()).read()),
+ "Script source cannot be empty");
+ }
+
+ /**
+ * Sets the script source.
+ *
+ * @param scriptSource how to get the script source
+ * @throws IOException if there were issues reading the script
+ */
+ @Nonnull @NotEmpty public void setScript(@Nonnull final Resource scriptSource) throws IOException {
+
+ Constraint.isNotNull(scriptSource, "Script source should not be null");
+
+ setScript(Constraint.isNotNull(scriptSource, "Script source can not be null or empty").getInputStream());
+ }
+
+ /**
+ * Gets the script language.
+ *
+ * @return the script language
*/
@Nonnull @NotEmpty public String getScriptLanguage() {
return scriptLanguage;
}
+ /**
+ * Sets the script language.
+ *
+ * @param what the script language
+ */
+ @Nonnull @NotEmpty public void setScriptLanguage(@Nonnull @NotEmpty final String what) {
+ scriptLanguage = Constraint.isNotNull(StringSupport.trimOrNull(what),
+ "Language must not be null");
+ }
+
/**
* Evaluates this script against the given bindings.
*
@@ -250,6 +352,7 @@ public final class EvaluableScript {
* @throws ScriptException thrown if there was a problem evaluating the script
*/
@Nullable public Object eval(@Nonnull final Bindings scriptBindings) throws ScriptException {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
if (compiledScript != null) {
return compiledScript.eval(scriptBindings);
}
@@ -266,27 +369,71 @@ public final class EvaluableScript {
* @throws ScriptException thrown if there was a problem evaluating the script
*/
@Nullable public Object eval(@Nonnull final ScriptContext scriptContext) throws ScriptException {
+ ComponentSupport.ifNotInitializedThrowUninitializedComponentException(this);
if (compiledScript != null) {
return compiledScript.eval(scriptContext);
}
return scriptEngine.eval(script, scriptContext);
}
- /**
+ /** {@inheritDoc}
* Initializes the scripting engine and compiles the script, if possible.
- *
- * @throws ScriptException thrown if the scripting engine supports compilation and the script does not compile
+ *
+ * @throws ComponentInitializationException if the scripting engine supports
+ * compilation and the script does not compile
*/
- private void initialize() throws ScriptException {
+ protected void doInitialize() throws ComponentInitializationException {
+
+ if ("".equals(scriptLanguage)) {
+ throw new ComponentInitializationException("Language must be non-empty");
+ }
+
+ if ("".equals(script)) {
+ throw new ComponentInitializationException("Sanguage must be non-empty");
+ }
+
final ScriptEngineManager engineManager = new ScriptEngineManager();
scriptEngine = engineManager.getEngineByName(scriptLanguage);
Constraint.isNotNull(scriptEngine, "No scripting engine associated with scripting language " + scriptLanguage);
if (scriptEngine instanceof Compilable) {
- compiledScript = ((Compilable) scriptEngine).compile(script);
+ try {
+ compiledScript = ((Compilable) scriptEngine).compile(script);
+ } catch (final ScriptException e) {
+ throw new ComponentInitializationException(e);
+ }
} else {
compiledScript = null;
}
}
-
+
+ /**
+ * Internal method to wrap {@link #initialize()}. This allows backwards compatibility with
+ * respect to the exception handling.
+ *
+ * We extract the cause from the Component Initialization and if it is a {@link ScriptException}
+ * throw that, otherwise we throw a new one which encapsulates the exception.
+ *
+ * Deprecation note. In most non-test cases the was to resolve this deprecation is to
+ * remove the method call (since most use is in bean generation and the initialize will be
+ * called). In every other case the answer is to use {@link #initialize()} and change the callers
+ * signature. Or just remove the whole thing.
+ *
+ * @throws ScriptException if there is a compilation issue.
+ * @deprecated Remove in V9.0.0
+ */
+ @Deprecated(forRemoval = true, since = "8.1.0")
+ public void initializeWithScriptException() throws ScriptException {
+
+ try {
+ initialize();
+ } catch (final ComponentInitializationException e) {
+ final Throwable cause = e.getCause();
+
+ if (cause != null && cause instanceof ScriptException) {
+ throw (ScriptException) cause;
+ }
+ throw new ScriptException(e);
+ }
+ }
}
diff --git a/src/test/java/net/shibboleth/utilities/java/support/scripting/EvaluableScriptTest.java b/src/test/java/net/shibboleth/utilities/java/support/scripting/EvaluableScriptTest.java
index 1ddf527..00223fd 100644
--- a/src/test/java/net/shibboleth/utilities/java/support/scripting/EvaluableScriptTest.java
+++ b/src/test/java/net/shibboleth/utilities/java/support/scripting/EvaluableScriptTest.java
@@ -22,12 +22,16 @@ import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
+import java.net.URI;
+import java.net.URL;
import javax.annotation.Nonnull;
import javax.script.ScriptException;
import net.shibboleth.utilities.java.support.annotation.constraint.NotEmpty;
+import net.shibboleth.utilities.java.support.component.ComponentInitializationException;
import net.shibboleth.utilities.java.support.logic.ConstraintViolationException;
+import net.shibboleth.utilities.java.support.resource.Resource;
import org.testng.Assert;
import org.testng.annotations.AfterClass;
@@ -52,7 +56,8 @@ public class EvaluableScriptTest {
}
}
- @Test public void testEvaluableScript() throws ScriptException, IOException {
+ @SuppressWarnings("removal")
+ @Test public void testEvaluableScriptDeprecated() throws ScriptException, IOException {
new EvaluableScript(SCRIPT_LANGUAGE, TEST_SIMPLE_SCRIPT);
@@ -91,10 +96,14 @@ public class EvaluableScriptTest {
}
Assert.assertEquals((new EvaluableScript(SCRIPT_LANGUAGE, theFile)).getScriptLanguage(), SCRIPT_LANGUAGE);
-
+
try (InputStream is = new FileInputStream(theFile)) {
Assert.assertEquals((new EvaluableScript(SCRIPT_LANGUAGE, is)).getScriptLanguage(), SCRIPT_LANGUAGE);
}
+
+ try (InputStream is = new FileInputStream(theFile)) {
+ Assert.assertEquals((new EvaluableScript(SCRIPT_LANGUAGE, resourceFor(is))).getScriptLanguage(), SCRIPT_LANGUAGE);
+ }
try {
new EvaluableScript(nullValue(), theFile);
@@ -109,7 +118,154 @@ public class EvaluableScriptTest {
} catch (final ConstraintViolationException e) {
// OK
}
+ }
+
+ private EvaluableScript testEvaluableScript(String language, String script) throws ComponentInitializationException {
+ final EvaluableScript ev = new EvaluableScript();
+ ev.setScriptLanguage(language);
+ ev.setScript(script);
+ ev.initialize();
+ return ev;
+ }
+
+ private EvaluableScript testEvaluableScript(String language, File script) throws ComponentInitializationException, IOException {
+ final EvaluableScript ev = new EvaluableScript();
+ ev.setScriptLanguage(language);
+ ev.setScript(script);
+ ev.initialize();
+ return ev;
+ }
+
+ private EvaluableScript testEvaluableScript(String language, InputStream script) throws ComponentInitializationException, IOException {
+ final EvaluableScript ev = new EvaluableScript();
+ ev.setScriptLanguage(language);
+ ev.setScript(script);
+ ev.initialize();
+ return ev;
+ }
+
+ private EvaluableScript testEvaluableScript(String language, Resource script) throws ComponentInitializationException, IOException {
+ final EvaluableScript ev = new EvaluableScript();
+ ev.setScriptLanguage(language);
+ ev.setScript(script);
+ ev.initialize();
+ return ev;
+ }
+
+ @Test public void testEvaluableScriptNonDeprecated() throws ScriptException, IOException, ComponentInitializationException {
+
+ testEvaluableScript(SCRIPT_LANGUAGE, TEST_SIMPLE_SCRIPT);
+
+ try {
+ testEvaluableScript(" ", TEST_SIMPLE_SCRIPT);
+ Assert.fail();
+ } catch (final ConstraintViolationException e) {
+ // OK
+ }
+
+ try {
+ testEvaluableScript(SCRIPT_LANGUAGE, " ");
+ Assert.fail();
+ } catch (final ConstraintViolationException e) {
+ // OK
+ }
+
+ try {
+ testEvaluableScript(nullValue(), TEST_SIMPLE_SCRIPT);
+ Assert.fail();
+ } catch (final ConstraintViolationException e) {
+ // OK
+ }
+
+ try {
+ testEvaluableScript(SCRIPT_LANGUAGE, (String) nullValue());
+ Assert.fail();
+ } catch (final ConstraintViolationException e) {
+ // OK
+ }
+
+ theFile = File.createTempFile("EvaluableScriptTest", ".js");
+
+ try (final FileWriter s = new FileWriter(theFile)) {
+ s.write(TEST_SIMPLE_SCRIPT, 0, TEST_SIMPLE_SCRIPT.length());
+ }
+
+ Assert.assertEquals((testEvaluableScript(SCRIPT_LANGUAGE, theFile)).getScriptLanguage(), SCRIPT_LANGUAGE);
+
+ try (InputStream is = new FileInputStream(theFile)) {
+ Assert.assertEquals((testEvaluableScript(SCRIPT_LANGUAGE, is)).getScriptLanguage(), SCRIPT_LANGUAGE);
+ }
+
+ try (InputStream is = new FileInputStream(theFile)) {
+ Assert.assertEquals((testEvaluableScript(SCRIPT_LANGUAGE, resourceFor(is))).getScriptLanguage(), SCRIPT_LANGUAGE);
+ }
+
+ try {
+ testEvaluableScript(nullValue(), theFile);
+ Assert.fail();
+ } catch (final ConstraintViolationException e) {
+ // OK
+ }
+
+ try {
+ testEvaluableScript(SCRIPT_LANGUAGE, (File) nullValue());
+ Assert.fail();
+ } catch (final ConstraintViolationException e) {
+ // OK
+ }
+ }
+
+ private Resource resourceFor(final InputStream is) {
+ return new Resource() {
+
+ public long lastModified() throws IOException {
+ return 0;
+ }
+
+ public boolean isReadable() {
+ return true;
+ }
+
+ public boolean isOpen() {
+ return false;
+ }
+
+ public URL getURL() throws IOException {
+ return null;
+ }
+
+ public URI getURI() throws IOException {
+ return null;
+ }
+
+ public InputStream getInputStream() throws IOException {
+ return is;
+ }
+
+ public String getFilename() {
+ return null;
+ }
+
+ public File getFile() throws IOException {
+ return null;
+ }
+
+ public String getDescription() {
+ return null;
+ }
+
+ public boolean exists() {
+ return true;
+ }
+
+ public Resource createRelativeResource(String relativePath) throws IOException {
+ return null;
+ }
+ public long contentLength() throws IOException {
+ return 0;
+ }
+ };
}
private <T> T nullValue() {
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the commits
mailing list