This is an automated email from the ASF dual-hosted git repository.

henrib pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-jexl.git


The following commit(s) were added to refs/heads/master by this push:
     new f1de9629 JEXL : improve JSR233 implementation; - avoid over-sharing 
engine instance;
f1de9629 is described below

commit f1de9629bc7ca441c967db3b3faba242b86c2804
Author: Henrib <[email protected]>
AuthorDate: Sat Jun 20 12:16:50 2026 +0200

    JEXL : improve JSR233 implementation;
    - avoid over-sharing engine instance;
---
 .../commons/jexl3/scripting/JexlScriptEngine.java  | 97 ++++++++++++++--------
 .../jexl3/scripting/JexlScriptEngineFactory.java   | 26 ++++--
 2 files changed, 80 insertions(+), 43 deletions(-)

diff --git 
a/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java 
b/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
index 3d9bb458..8daa7a1a 100644
--- a/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
+++ b/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngine.java
@@ -65,6 +65,59 @@ import org.apache.commons.logging.LogFactory;
  * @since 2.0
  */
 public class JexlScriptEngine extends AbstractScriptEngine implements 
Compilable {
+    /**
+     * A factory that shares the JexlEngine instance between all 
JexlScriptEngine instances it creates.
+     * <p>All JexlScriptEngine instances created by this factory share the 
same JexlEngine instance and JexlUberspect instance.</p>
+     * <p>To create a JexlScriptEngine with a different JexlEngine instance,
+     * use the {@link 
JexlScriptEngine#JexlScriptEngine(JexlScriptEngineFactory)} constructor.</p>
+     * @since 3.3
+     */
+    public static class Factory extends JexlScriptEngineFactory {
+        /**
+         * The shared engine instance.
+         * <p>A single soft-reference JEXL engine and JexlUberspect is shared 
by all instances of JexlScriptEngine
+         * created by this factory.</p>
+         */
+        private Reference<JexlEngine> engineReference;
+
+        /** Default constructor. */
+        public Factory() {
+            this(null);
+        }
+
+        /**
+         * For specialization.
+         * @param permissions the permissions to use for the engine
+         */
+        public Factory(JexlPermissions permissions) {
+            super(permissions);
+        }
+
+        @Override
+        protected JexlEngine getEngine() {
+            Reference<JexlEngine> ref = engineReference;
+            JexlEngine engine = ref != null ? ref.get() : null;
+            if (engine == null) {
+                synchronized (this) {
+                    ref = engineReference;
+                    engine = ref != null ? ref.get() : null;
+                    if (engine == null) {
+                        engine = createJexlEngine();
+                        engineReference = new SoftReference<>(engine);
+                    }
+                }
+            }
+            return engine;
+        }
+
+        /**
+         * Sets the shared engine instance.
+         * @param engine the engine
+         */
+        void setEngine(JexlEngine engine) {
+            engineReference = new SoftReference<>(engine);
+        }
+    }
 
     /**
      * Holds singleton JexlScriptEngineFactory (IODH).
@@ -72,7 +125,7 @@ public class JexlScriptEngine extends AbstractScriptEngine 
implements Compilable
     private static final class FactorySingletonHolder {
 
         /** The engine factory singleton instance. */
-        static final JexlScriptEngineFactory DEFAULT_FACTORY = new 
JexlScriptEngineFactory();
+        static final Factory DEFAULT_FACTORY = new Factory();
 
         /** Non instantiable. */
         private FactorySingletonHolder() {}
@@ -260,11 +313,6 @@ public class JexlScriptEngine extends AbstractScriptEngine 
implements Compilable
         }
     }
 
-    /**
-     * The shared engine instance.
-     * <p>A single soft-reference JEXL engine and JexlUberspect is shared by 
all instances of JexlScriptEngine.</p>
-     */
-    private static Reference<JexlEngine> engineReference;
 
     /** The logger. */
     static final Log LOG = LogFactory.getLog(JexlScriptEngine.class);
@@ -281,29 +329,6 @@ public class JexlScriptEngine extends AbstractScriptEngine 
implements Compilable
     /** Reserved key for script. */
     private static final String SCRIPT = "script";
 
-    /**
-     * @return the shared JexlEngine instance, create it if necessary
-     */
-    private static JexlEngine getEngine(ScriptEngineFactory 
scriptEngineFactory) {
-        Reference<JexlEngine> ref = engineReference;
-        JexlEngine engine = ref != null ? ref.get() : null;
-        if (engine == null) {
-            synchronized (JexlScriptEngineFactory.class) {
-                ref = engineReference;
-                engine = ref != null ? ref.get() : null;
-                if (engine == null) {
-                    if (!(scriptEngineFactory instanceof 
JexlScriptEngineFactory)) {
-                        throw new 
IllegalArgumentException("ScriptEngineFactory is not JexlScriptEngineFactory");
-                    }
-                    JexlScriptEngineFactory factory = 
(JexlScriptEngineFactory) scriptEngineFactory;
-                    engine = factory.createJexlEngine();
-                    engineReference = new SoftReference<>(engine);
-                }
-            }
-        }
-        return engine;
-    }
-
     /**
      * Reads from a reader into a local buffer and return a String with
      * the contents of the reader.
@@ -344,7 +369,7 @@ public class JexlScriptEngine extends AbstractScriptEngine 
implements Compilable
     }
 
     /**
-     * Sets the shared instance used for the script engine.
+     * Sets the shared instance used for the script engine in the default 
factory.
      * <p>This should be called early enough to have an effect, ie before any
      * {@link javax.script.ScriptEngineManager} features.</p>
      * <p>To restore 3.2 script behavior:</p>
@@ -360,12 +385,14 @@ public class JexlScriptEngine extends 
AbstractScriptEngine implements Compilable
      * @since 3.3
      */
     public static void setInstance(final JexlEngine engine) {
-        engineReference = new SoftReference<>(engine);
+        FactorySingletonHolder.DEFAULT_FACTORY.setEngine(engine);
     }
 
     /**
      * Sets the permissions instance used to create the script engine.
-     * <p>This method has been considered unsafe and is no longer 
supported.</p>
+     * <p>This method has been considered unsafe and is no longer supported.
+     * Use {@link 
JexlScriptEngineFactory#setDefaultPermissions(JexlPermissions)} during 
initialization
+     * - <em>before</em> requesting an engine - to achieve the intended 
permission injection.</p>
      * @deprecated 3.6.3
      * @param permissions unused, method will throw
      */
@@ -378,7 +405,7 @@ public class JexlScriptEngine extends AbstractScriptEngine 
implements Compilable
     final JexlScriptObject jexlObject;
 
     /** The factory which created this instance. */
-    final ScriptEngineFactory parentFactory;
+    final JexlScriptEngineFactory parentFactory;
 
     /** The JEXL EL engine. */
     final JexlEngine jexlEngine;
@@ -399,10 +426,10 @@ public class JexlScriptEngine extends 
AbstractScriptEngine implements Compilable
      * @param scriptEngineFactory the factory which created this instance.
      * @throws NullPointerException if factory is null
      */
-    public JexlScriptEngine(final ScriptEngineFactory scriptEngineFactory) {
+    public JexlScriptEngine(final JexlScriptEngineFactory scriptEngineFactory) 
{
         Objects.requireNonNull(scriptEngineFactory, "scriptEngineFactory");
         parentFactory = scriptEngineFactory;
-        jexlEngine = getEngine(scriptEngineFactory);
+        jexlEngine = scriptEngineFactory.getEngine();
         jexlObject = new JexlScriptObject();
     }
 
diff --git 
a/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngineFactory.java 
b/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngineFactory.java
index 3ddf190c..2229319f 100644
--- 
a/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngineFactory.java
+++ 
b/src/main/java/org/apache/commons/jexl3/scripting/JexlScriptEngineFactory.java
@@ -57,22 +57,37 @@ public class JexlScriptEngineFactory implements 
ScriptEngineFactory {
      */
     private final JexlPermissions permissions;
 
-    /** Default constructor */
+    /**
+     * Default constructor.
+     */
     public JexlScriptEngineFactory() { this(null); } // Keep Javadoc happy
 
     /**
      * Constructor with permissions.
-     * <p>Meant to reduce dependency to JEXL for extraordinary case of JSR233 
</p>
+     * <p>Meant to reduce dependency to JEXL for extraordinary use case of 
JSR233.</p>
      * @param jexlPermissions the permissions instance to use or null to use 
the {@link JexlScriptEngineFactory} default
      */
     public JexlScriptEngineFactory(JexlPermissions jexlPermissions) {
         permissions = jexlPermissions != null ? jexlPermissions : 
defaultPermissions;
     }
 
+    @Override
+    public ScriptEngine getScriptEngine() {
+        return new JexlScriptEngine(this);
+    }
+
+    /**
+     * Creates an engine.
+     * @return the JexlEngine instance, create it if necessary
+     */
+    protected JexlEngine getEngine() {
+        return createJexlEngine();
+    }
+
     /**
      * @return a new JexlEngine instance
      */
-    JexlEngine createJexlEngine() {
+    protected JexlEngine createJexlEngine() {
         JexlBuilder builder = new JexlBuilder()
           .strict(true)
           .safe(false)
@@ -210,9 +225,4 @@ public class JexlScriptEngineFactory implements 
ScriptEngineFactory {
         return sb.toString();
     }
 
-    @Override
-    public ScriptEngine getScriptEngine() {
-        return new JexlScriptEngine(this);
-    }
-
 }

Reply via email to