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);
- }
-
}