[java-support] 02/10: JSPT-96 Deprecate all parameterized constructors to EvaluableScript

Rod Widdowson rdw at steadingsoftware.com
Wed Jun 10 14:21:51 UTC 2020


This is an automated email from the git hooks/post-receive script.

rdw pushed a commit to branch master
in repository java-support.

View the commit online:
http://git.shibboleth.net/view/?p=java-support.git;a=commit;h=c9223a887260144f5d3908022b0cf5e67f470f9a

commit c9223a887260144f5d3908022b0cf5e67f470f9a
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