You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2017/12/03 12:25:01 UTC
[sling-org-apache-sling-scripting-core] 01/01: SLING-7134 - Script
execution order is not deterministic on Java 9
This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch issue/SLING-7134
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-core.git
commit 2e15bd4f230d390ceadc9481627156bb3b6caaa3
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Sun Dec 3 13:23:55 2017 +0100
SLING-7134 - Script execution order is not deterministic on Java 9
* reimplemented the former o.a.s.scripting.core.impl.ScriptEngineManagerFactory,
o.a.s.scripting.core.impl.helper.SlingScriptEngineManager and
o.a.s.scripting.core.impl.helper.ProxyScriptEngineManager into one service:
o.a.s.scripting.core.impl.jsr223.SlingScriptEngineManager
* the new SlingScriptEngineManager manages ScriptEngineFactories registrations
from the platform's ScriptEngineManager, bundles that expose a ScriptEngineFactory
through the SPI mechanism and ScriptEngineFactories registered as OSGi services
* introduced the concept of a SortableScriptEngineFactory, that allows ordering the
factories based on bundle IDs and service rankings; if two factories have the same service
ranking, then the factory with the higher bundle ID will win
* corrected bug in the ScriptCacheImpl to cache scripts from all ScriptEngineFactories that
register a Compilable ScriptEngine, not just for the ScriptEngineFactories registered as
OSGi services
* extended tests
* updated PAX exam tests to run on Java 9
---
pom.xml | 21 +-
.../impl/BindingsValuesProvidersByContextImpl.java | 4 +-
.../sling/scripting/core/impl/ScriptCacheImpl.java | 52 ++--
.../core/impl/ScriptEngineConsolePlugin.java | 109 +++----
.../core/impl/ScriptEngineManagerFactory.java | 281 ------------------
.../core/impl/SlingScriptAdapterFactory.java | 2 +-
.../core/impl/helper/ProxyScriptEngineManager.java | 107 -------
.../core/impl/helper/SlingScriptEngineManager.java | 77 -----
.../core/impl/jsr223/SlingScriptEngineManager.java | 320 +++++++++++++++++++++
.../impl/jsr223/SortableScriptEngineFactory.java | 134 +++++++++
.../sling/scripting/core/ScriptHelperTest.java | 6 +-
.../core/impl/ScriptEngineManagerFactoryTest.java | 168 -----------
.../{ => jsr223}/DummyScriptEngineFactory.java | 36 +--
.../impl/jsr223/SlingScriptEngineManagerTest.java | 208 ++++++++++++++
.../jsr223/SortableScriptEngineFactoryTest.java | 174 +++++++++++
.../core/it/ScriptingCoreTestSupport.java | 16 +-
16 files changed, 957 insertions(+), 758 deletions(-)
diff --git a/pom.xml b/pom.xml
index a49404b..9166e97 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
<parent>
<groupId>org.apache.sling</groupId>
<artifactId>sling</artifactId>
- <version>30</version>
+ <version>32</version>
<relativePath />
</parent>
@@ -37,7 +37,7 @@
</description>
<properties>
- <org.ops4j.pax.exam.version>4.10.0</org.ops4j.pax.exam.version>
+ <org.ops4j.pax.exam.version>4.11.0</org.ops4j.pax.exam.version>
</properties>
<scm>
@@ -140,7 +140,7 @@
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.commons.osgi</artifactId>
- <version>2.1.0</version>
+ <version>2.4.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -182,7 +182,7 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.webconsole</artifactId>
- <version>3.1.8</version>
+ <version>4.2.0</version>
<scope>provided</scope>
</dependency>
<dependency>
@@ -221,23 +221,28 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.framework</artifactId>
- <version>5.6.2</version>
+ <version>5.6.10</version>
<scope>test</scope>
</dependency>
-
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.osgi-mock</artifactId>
- <version>2.0.2</version>
+ <version>2.3.5-SNAPSHOT</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.apache.sling</groupId>
<artifactId>org.apache.sling.testing.sling-mock</artifactId>
- <version>1.6.0</version>
+ <version>2.2.14</version>
<scope>test</scope>
+ <exclusions>
+ <exclusion>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.scripting.core</artifactId>
+ </exclusion>
+ </exclusions>
</dependency>
<dependency>
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java b/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java
index b8fdec5..63f439c 100644
--- a/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextImpl.java
@@ -34,7 +34,7 @@ import javax.script.ScriptEngineFactory;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.apache.sling.scripting.api.BindingsValuesProvider;
import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
-import org.apache.sling.scripting.core.impl.helper.SlingScriptEngineManager;
+import org.apache.sling.scripting.core.impl.jsr223.SlingScriptEngineManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
@@ -151,7 +151,7 @@ public class BindingsValuesProvidersByContextImpl implements BindingsValuesProvi
// we load the compatible language ones first so that the most specific
// overrides these
- Map<Object, Object> factoryProps = scriptEngineManager.getProperties(scriptEngineFactory);
+ Map<String, Object> factoryProps = scriptEngineManager.getProperties(scriptEngineFactory);
if (factoryProps != null) {
String[] compatibleLangs = PropertiesUtil.toStringArray(factoryProps.get("compatible.javax.script.name"), new String[0]);
for (final String name : compatibleLangs) {
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java b/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java
index 013e758..a17e05d 100644
--- a/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java
@@ -47,6 +47,7 @@ import org.apache.sling.commons.threads.ThreadPoolManager;
import org.apache.sling.scripting.api.CachedScript;
import org.apache.sling.scripting.api.ScriptCache;
import org.apache.sling.scripting.core.impl.helper.CachingMap;
+import org.apache.sling.scripting.core.impl.jsr223.SlingScriptEngineManager;
import org.apache.sling.serviceusermapping.ServiceUserMapped;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
@@ -57,22 +58,18 @@ import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@Component(
- service = ScriptCache.class,
- reference = @Reference(
- name = "ScriptEngineFactory",
- bind = "bindScriptEngineFactory",
- unbind = "unbindScriptEngineFactory",
- service = ScriptEngineFactory.class,
- cardinality = ReferenceCardinality.MULTIPLE,
- policy = ReferencePolicy.DYNAMIC
- ),
+ service = {ScriptCache.class, EventHandler.class},
property = {
- Constants.SERVICE_VENDOR + "=The Apache Software Foundation"
+ Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
+ EventConstants.EVENT_TOPIC + "=org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManager/*"
}
)
@Designate(
@@ -82,7 +79,7 @@ import org.slf4j.LoggerFactory;
* The {@code ScriptCache} stores information about {@link CompiledScript} instances evaluated by various {@link ScriptEngine}s that
* implement the {@link Compilable} interface.
*/
-public class ScriptCacheImpl implements ScriptCache, ResourceChangeListener, ExternalResourceChangeListener {
+public class ScriptCacheImpl implements ScriptCache, ResourceChangeListener, ExternalResourceChangeListener, EventHandler {
private final Logger LOGGER = LoggerFactory.getLogger(ScriptCacheImpl.class);
@@ -102,6 +99,9 @@ public class ScriptCacheImpl implements ScriptCache, ResourceChangeListener, Ext
@Reference
private ThreadPoolManager threadPoolManager;
+ @Reference
+ private SlingScriptEngineManager slingScriptEngineManager;
+
private ThreadPool threadPool;
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
private final Lock readLock = rwl.readLock();
@@ -284,27 +284,17 @@ public class ScriptCacheImpl implements ScriptCache, ResourceChangeListener, Ext
active = false;
}
- protected void bindScriptEngineFactory(ScriptEngineFactory scriptEngineFactory) {
- ScriptEngine engine = scriptEngineFactory.getScriptEngine();
- if (engine instanceof Compilable) {
- /**
- * we only care about creating an EventHandler that monitors scripts generated by script engines which implement Compilable
- */
- for (String extension : scriptEngineFactory.getExtensions()) {
- extensions.add(extension);
- }
- if (active) {
- configureCache();
+ @Override
+ public void handleEvent(Event event) {
+ extensions.clear();
+ for (ScriptEngineFactory factory : slingScriptEngineManager.getEngineFactories()) {
+ ScriptEngine scriptEngine = factory.getScriptEngine();
+ if (scriptEngine instanceof Compilable) {
+ extensions.addAll(factory.getExtensions());
+ if (active) {
+ configureCache();
+ }
}
}
}
-
- protected void unbindScriptEngineFactory(ScriptEngineFactory scriptEngineFactory) {
- for (String extension : scriptEngineFactory.getExtensions()) {
- extensions.remove(extension);
- }
- if (active) {
- configureCache();
- }
- }
}
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/ScriptEngineConsolePlugin.java b/src/main/java/org/apache/sling/scripting/core/impl/ScriptEngineConsolePlugin.java
index 59b2658..1b88807 100644
--- a/src/main/java/org/apache/sling/scripting/core/impl/ScriptEngineConsolePlugin.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/ScriptEngineConsolePlugin.java
@@ -18,7 +18,9 @@
*/
package org.apache.sling.scripting.core.impl;
+import java.io.IOException;
import java.io.PrintWriter;
+import java.util.Arrays;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Iterator;
@@ -26,57 +28,59 @@ import java.util.List;
import javax.script.ScriptEngineFactory;
import javax.script.ScriptEngineManager;
-
+import javax.servlet.Servlet;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
+import org.apache.sling.scripting.core.impl.jsr223.SlingScriptEngineManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceRegistration;
-
-public class ScriptEngineConsolePlugin {
-
- // --------- setup and shutdown
-
- private static ScriptEngineConsolePlugin INSTANCE;
-
- static void initPlugin(BundleContext context,
- ScriptEngineManagerFactory scriptEngineManagerFactory) {
- if (INSTANCE == null) {
- ScriptEngineConsolePlugin tmp = new ScriptEngineConsolePlugin(
- scriptEngineManagerFactory);
- tmp.activate(context);
- INSTANCE = tmp;
- }
- }
-
- static void destroyPlugin() {
- if (INSTANCE != null) {
- try {
- INSTANCE.deactivate();
- } finally {
- INSTANCE = null;
- }
- }
- }
-
- private ServiceRegistration serviceRegistration;
-
- private final ScriptEngineManagerFactory scriptEngineManagerFactory;
-
- // private constructor to force using static setup and shutdown
- private ScriptEngineConsolePlugin(
- ScriptEngineManagerFactory scriptEngineManagerFactory) {
- this.scriptEngineManagerFactory = scriptEngineManagerFactory;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+
+@Component(
+ property = {
+ Constants.SERVICE_DESCRIPTION + "=Web Console Plugin for ScriptEngine implementations",
+ Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
+ WebConsoleConstants.PLUGIN_LABEL + "=" + ScriptEngineConsolePlugin.CONSOLE_LABEL,
+ WebConsoleConstants.PLUGIN_TITLE + "=" + ScriptEngineConsolePlugin.CONSOLE_TITLE,
+ WebConsoleConstants.CONFIG_PRINTER_MODES + "=always",
+ WebConsoleConstants.PLUGIN_CATEGORY + "=Status"
+ },
+ service = { Servlet.class }
+)
+public class ScriptEngineConsolePlugin extends AbstractWebConsolePlugin {
+
+ public static final String CONSOLE_LABEL = "slingscripting";
+ public static final String CONSOLE_TITLE = "Script Engines";
+
+ @Reference
+ private SlingScriptEngineManager slingScriptEngineManager;
+
+ @Override
+ public String getTitle() {
+ return CONSOLE_TITLE;
}
- public String getTitle() {
- return "Script Engines";
+ @Override
+ public String getLabel() {
+ return CONSOLE_LABEL;
}
- public void printConfiguration(final PrintWriter pw) {
+ @Override
+ protected void renderContent(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
+ throws IOException {
+ PrintWriter pw = httpServletResponse.getWriter();
+ pw.println("<div id='content' class='ui-widget'><br>");
+ pw.println("<pre>");
pw.println("Available Script Engines");
pw.println("========================");
- ScriptEngineManager manager = scriptEngineManagerFactory.getScriptEngineManager();
- List<?> factories = manager.getEngineFactories();
+ List<?> factories = slingScriptEngineManager.getEngineFactories();
for (Iterator<?> fi = factories.iterator(); fi.hasNext();) {
final ScriptEngineFactory factory = (ScriptEngineFactory) fi.next();
@@ -100,6 +104,8 @@ public class ScriptEngineConsolePlugin {
pw.print("- Names : ");
printArray(pw, factory.getNames());
}
+ pw.println("</pre>");
+ pw.println("</div>");
}
private void printArray(PrintWriter pw, List<?> values) {
@@ -116,25 +122,4 @@ public class ScriptEngineConsolePlugin {
}
}
- public void activate(BundleContext context) {
- final Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put(Constants.SERVICE_DESCRIPTION,
- "Web Console Plugin for ScriptEngine implementations");
- props.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
- props.put(Constants.SERVICE_PID, getClass().getName());
-
- props.put("felix.webconsole.label", "slingscripting");
- props.put("felix.webconsole.title", "Script Engines");
- props.put("felix.webconsole.configprinter.modes", "always");
-
- serviceRegistration = context.registerService(
- this.getClass().getName(), this, props);
- }
-
- public void deactivate() {
- if (serviceRegistration != null) {
- serviceRegistration.unregister();
- serviceRegistration = null;
- }
- }
}
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/ScriptEngineManagerFactory.java b/src/main/java/org/apache/sling/scripting/core/impl/ScriptEngineManagerFactory.java
deleted file mode 100644
index e851676..0000000
--- a/src/main/java/org/apache/sling/scripting/core/impl/ScriptEngineManagerFactory.java
+++ /dev/null
@@ -1,281 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * 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 org.apache.sling.scripting.core.impl;
-
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-
-import javax.script.ScriptEngineFactory;
-import javax.script.ScriptEngineManager;
-
-import org.apache.sling.api.scripting.SlingScriptConstants;
-import org.apache.sling.scripting.core.impl.helper.ProxyScriptEngineManager;
-import org.apache.sling.scripting.core.impl.helper.SlingScriptEngineManager;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.component.ComponentContext;
-import org.osgi.service.component.annotations.Component;
-import org.osgi.service.component.annotations.Reference;
-import org.osgi.service.component.annotations.ReferenceCardinality;
-import org.osgi.service.component.annotations.ReferencePolicy;
-import org.osgi.service.component.annotations.ReferencePolicyOption;
-import org.osgi.service.event.Event;
-import org.osgi.service.event.EventAdmin;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Component which exposes a ScriptEngineManager service.
- *
- */
-@Component(service = {})
-public class ScriptEngineManagerFactory implements BundleListener {
-
- private final Logger log = LoggerFactory.getLogger(ScriptEngineManagerFactory.class);
-
- private static final String ENGINE_FACTORY_SERVICE = "META-INF/services/" + ScriptEngineFactory.class.getName();
-
- private BundleContext bundleContext;
-
- /**
- * Event admin is optional
- */
- @Reference(policy = ReferencePolicy.DYNAMIC,
- policyOption = ReferencePolicyOption.GREEDY,
- cardinality=ReferenceCardinality.OPTIONAL)
- private volatile EventAdmin eventAdmin;
-
- /**
- * The proxy to the actual ScriptEngineManager. This proxy is actually
- * registered as the ScriptEngineManager service for the lifetime of
- * this factory.
- */
- private final ProxyScriptEngineManager scriptEngineManager = new ProxyScriptEngineManager();
-
- private final Set<Bundle> engineSpiBundles = new HashSet<>();
-
- private final Map<ScriptEngineFactory, Map<Object, Object>> engineSpiServices = new HashMap<>();
-
- private ServiceRegistration scriptEngineManagerRegistration;
-
- /**
- * Refresh the script engine manager.
- */
- private void refreshScriptEngineManager() {
- // create (empty) script engine manager
- final ClassLoader loader = getClass().getClassLoader();
- final SlingScriptEngineManager tmp = new SlingScriptEngineManager(loader);
-
- // register script engines from bundles
- synchronized (this.engineSpiBundles) {
- for (final Bundle bundle : this.engineSpiBundles) {
- registerFactories(tmp, bundle);
- }
- }
-
- // register script engines from registered services
- synchronized (this.engineSpiServices) {
- for (final Map.Entry<ScriptEngineFactory, Map<Object, Object>> factory : this.engineSpiServices.entrySet()) {
- registerFactory(tmp, factory.getKey(), factory.getValue());
- }
- }
-
- scriptEngineManager.setDelegatee(tmp);
-
- final List<ScriptEngineFactory> factories = tmp.getEngineFactories();
- for (final ScriptEngineFactory factory : factories) {
- log.info("ScriptEngine {}/{} is now handling {}, {}, {}.", new Object[]{factory.getEngineName(), factory.getEngineVersion(), factory.getExtensions(), factory.getMimeTypes(), factory.getNames()});
- }
- }
-
- @SuppressWarnings("unchecked")
- private void registerFactories(final SlingScriptEngineManager mgr, final Bundle bundle) {
- URL url = bundle.getEntry(ENGINE_FACTORY_SERVICE);
- InputStream ins = null;
- try {
- ins = url.openStream();
- BufferedReader reader = new BufferedReader(new InputStreamReader(ins));
- String line;
- while ((line = reader.readLine()) != null) {
- if (!line.startsWith("#") && line.trim().length() > 0) {
- try {
- Class<ScriptEngineFactory> clazz = (Class<ScriptEngineFactory>) bundle.loadClass(line);
- ScriptEngineFactory spi = clazz.newInstance();
- registerFactory(mgr, spi, null);
- } catch (Throwable t) {
- log.error("Cannot register ScriptEngineFactory " + line, t);
- }
- }
- }
- } catch (IOException ioe) {
- // ignore
- } finally {
- if (ins != null) {
- try {
- ins.close();
- } catch (IOException ioe) {
- }
- }
- }
- }
-
- private void registerFactory(final SlingScriptEngineManager mgr, final ScriptEngineFactory factory, final Map<Object, Object> props) {
- log.info("Adding ScriptEngine {}/{} for language {}/{}.", new Object[]{factory.getEngineName(), factory.getEngineVersion(), factory.getLanguageName(), factory.getLanguageVersion()});
- mgr.registerScriptEngineFactory(factory, props);
- }
-
- // ---------- BundleListener interface -------------------------------------
-
- @Override
- public void bundleChanged(BundleEvent event) {
- if (event.getType() == BundleEvent.STARTED
- && event.getBundle().getEntry(ENGINE_FACTORY_SERVICE) != null) {
- synchronized (this.engineSpiBundles) {
- this.engineSpiBundles.add(event.getBundle());
- }
- this.refreshScriptEngineManager();
- } else if (event.getType() == BundleEvent.STOPPED) {
- boolean refresh;
- synchronized (this.engineSpiBundles) {
- refresh = this.engineSpiBundles.remove(event.getBundle());
- }
- if (refresh) {
- this.refreshScriptEngineManager();
- }
- }
- }
-
- // ---------- SCR integration ----------------------------------------------
-
- protected void activate(ComponentContext context) {
- this.bundleContext = context.getBundleContext();
-
- this.bundleContext.addBundleListener(this);
-
- Bundle[] bundles = this.bundleContext.getBundles();
- synchronized (this.engineSpiBundles) {
- for (Bundle bundle : bundles) {
- if (bundle.getState() == Bundle.ACTIVE
- && bundle.getEntry(ENGINE_FACTORY_SERVICE) != null) {
- this.engineSpiBundles.add(bundle);
- }
- }
- }
-
- // create a script engine manager
- this.refreshScriptEngineManager();
-
- scriptEngineManagerRegistration = this.bundleContext.registerService(
- new String[] { ScriptEngineManager.class.getName(),
- SlingScriptEngineManager.class.getName() },
- scriptEngineManager, new Hashtable<String, Object>());
-
- org.apache.sling.scripting.core.impl.ScriptEngineConsolePlugin.initPlugin(context.getBundleContext(), this);
- }
-
- protected void deactivate(ComponentContext context) {
- org.apache.sling.scripting.core.impl.ScriptEngineConsolePlugin.destroyPlugin();
-
- context.getBundleContext().removeBundleListener(this);
-
- if (scriptEngineManagerRegistration != null) {
- scriptEngineManagerRegistration.unregister();
- scriptEngineManagerRegistration = null;
- }
-
- synchronized ( this ) {
- this.engineSpiBundles.clear();
- this.engineSpiServices.clear();
- }
-
- scriptEngineManager.setDelegatee(null);
-
- this.bundleContext = null;
- }
-
- @Reference(service = ScriptEngineFactory.class,
- policy = ReferencePolicy.DYNAMIC,
- cardinality = ReferenceCardinality.MULTIPLE)
- protected void bindScriptEngineFactory(final ScriptEngineFactory scriptEngineFactory, final Map<Object, Object> props) {
- if (scriptEngineFactory != null) {
- synchronized ( this.engineSpiServices) {
- this.engineSpiServices.put(scriptEngineFactory, props);
- }
-
- this.refreshScriptEngineManager();
-
- // send event
- postEvent(SlingScriptConstants.TOPIC_SCRIPT_ENGINE_FACTORY_ADDED, scriptEngineFactory);
- }
- }
-
- protected void unbindScriptEngineFactory(final ScriptEngineFactory scriptEngineFactory) {
- boolean refresh;
- synchronized (this.engineSpiServices) {
- refresh = this.engineSpiServices.remove(scriptEngineFactory) != null;
- }
-
- if (refresh) {
- this.refreshScriptEngineManager();
- }
-
- // send event
- postEvent(SlingScriptConstants.TOPIC_SCRIPT_ENGINE_FACTORY_REMOVED, scriptEngineFactory);
- }
-
- private String[] toArray(final List<String> list) {
- return list.toArray(new String[list.size()]);
- }
-
- /**
- * Post a notification with the EventAdmin
- */
- private void postEvent(final String topic, final ScriptEngineFactory scriptEngineFactory) {
- final EventAdmin localEA = this.eventAdmin;
- if (localEA != null) {
- final Dictionary<String, Object> props = new Hashtable<>();
- props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_NAME, scriptEngineFactory.getEngineName());
- props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_VERSION, scriptEngineFactory.getEngineVersion());
- props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_EXTENSIONS, toArray(scriptEngineFactory.getExtensions()));
- props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_LANGUAGE_NAME, scriptEngineFactory.getLanguageName());
- props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_LANGUAGE_VERSION, scriptEngineFactory.getLanguageVersion());
- props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_MIME_TYPES, toArray(scriptEngineFactory.getMimeTypes()));
- localEA.postEvent(new Event(topic, props));
- }
- }
-
- /**
- * Get the script engine manager.
- * Refresh the manager if changes occurred.
- */
- ScriptEngineManager getScriptEngineManager() {
- return this.scriptEngineManager;
- }
-}
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java b/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
index 04b6cb2..4b94191 100644
--- a/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
+++ b/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
@@ -27,7 +27,7 @@ import org.apache.sling.commons.mime.MimeTypeProvider;
import org.apache.sling.scripting.api.BindingsValuesProvider;
import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
import org.apache.sling.scripting.api.ScriptCache;
-import org.apache.sling.scripting.core.impl.helper.SlingScriptEngineManager;
+import org.apache.sling.scripting.core.impl.jsr223.SlingScriptEngineManager;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.service.component.ComponentContext;
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/helper/ProxyScriptEngineManager.java b/src/main/java/org/apache/sling/scripting/core/impl/helper/ProxyScriptEngineManager.java
deleted file mode 100644
index d699828..0000000
--- a/src/main/java/org/apache/sling/scripting/core/impl/helper/ProxyScriptEngineManager.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF 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 org.apache.sling.scripting.core.impl.helper;
-
-import java.util.List;
-import java.util.Map;
-
-import javax.script.Bindings;
-import javax.script.ScriptEngine;
-import javax.script.ScriptEngineFactory;
-
-public class ProxyScriptEngineManager extends SlingScriptEngineManager {
-
- private SlingScriptEngineManager delegatee;
-
- public ProxyScriptEngineManager() {
- setDelegatee(null);
- }
-
- public void setDelegatee(SlingScriptEngineManager delegatee) {
- this.delegatee = (delegatee == null)
- ? new SlingScriptEngineManager()
- : delegatee;
- }
-
- public Object get(String key) {
- return delegatee.get(key);
- }
-
- public ScriptEngine getEngineByExtension(String extension) {
- return delegatee.getEngineByExtension(extension);
- }
-
- public ScriptEngine getEngineByMimeType(String mimeType) {
- return delegatee.getEngineByMimeType(mimeType);
- }
-
- public ScriptEngine getEngineByName(String shortName) {
- return delegatee.getEngineByName(shortName);
- }
-
- public List<ScriptEngineFactory> getEngineFactories() {
- return delegatee.getEngineFactories();
- }
-
- public Map<Object, Object> getProperties(ScriptEngineFactory factory) {
- return delegatee.getProperties(factory);
- }
-
- public void put(String key, Object value) {
- delegatee.put(key, value);
- }
-
- public void registerEngineExtension(String extension,
- ScriptEngineFactory factory) {
- delegatee.registerEngineExtension(extension, factory);
- }
-
- public void registerEngineMimeType(String type, ScriptEngineFactory factory) {
- delegatee.registerEngineMimeType(type, factory);
- }
-
- public void registerEngineName(String name, ScriptEngineFactory factory) {
- delegatee.registerEngineName(name, factory);
- }
-
- public void registerScriptEngineFactory(ScriptEngineFactory factory,
- Map<Object, Object> props) {
- delegatee.registerScriptEngineFactory(factory, props);
- }
-
- // Livetribe JSR-223 2.0.6 API
- public Bindings getGlobalScope()
- {
- return getBindings();
- }
-
- // Livetribe JSR-223 2.0.6 API
- public void setGlobalScope(Bindings globalScope)
- {
- setBindings(globalScope);
- }
-
- public Bindings getBindings() {
- return delegatee.getBindings();
- }
-
- public void setBindings(Bindings bindings) {
- delegatee.setBindings(bindings);
- }
-}
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/helper/SlingScriptEngineManager.java b/src/main/java/org/apache/sling/scripting/core/impl/helper/SlingScriptEngineManager.java
deleted file mode 100644
index 32f727e..0000000
--- a/src/main/java/org/apache/sling/scripting/core/impl/helper/SlingScriptEngineManager.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF 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 org.apache.sling.scripting.core.impl.helper;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import javax.script.ScriptEngineFactory;
-import javax.script.ScriptEngineManager;
-
-
-public class SlingScriptEngineManager extends ScriptEngineManager {
-
- private final List<ScriptEngineFactory> factories = new ArrayList<ScriptEngineFactory>();
- private final Map<ScriptEngineFactory, Map<Object, Object>> factoryProperties = new HashMap<ScriptEngineFactory, Map<Object, Object>>();
-
- public SlingScriptEngineManager(ClassLoader classLoader) {
- super(classLoader);
- }
-
- public SlingScriptEngineManager() {
- super();
- }
-
- @Override
- public List<ScriptEngineFactory> getEngineFactories() {
- List<ScriptEngineFactory> baseFactories = super.getEngineFactories();
-
- List<ScriptEngineFactory> result = new ArrayList<ScriptEngineFactory>();
- result.addAll(factories);
- result.addAll(baseFactories);
- return result;
- }
-
- public Map<Object, Object> getProperties(ScriptEngineFactory factory) {
- return factoryProperties.get(factory);
- }
-
- public void registerScriptEngineFactory(ScriptEngineFactory factory, Map<Object, Object> props) {
- for (Object ext : factory.getExtensions()) {
- registerEngineExtension((String) ext, factory);
- }
-
- for (Object mime : factory.getMimeTypes()) {
- registerEngineMimeType((String) mime, factory);
- }
-
- for (Object name : factory.getNames()) {
- registerEngineName((String) name, factory);
- }
-
- factories.add(factory);
-
- if (props != null) {
- factoryProperties.put(factory, props);
- }
- }
-
-}
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManager.java b/src/main/java/org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManager.java
new file mode 100644
index 0000000..8c52960
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManager.java
@@ -0,0 +1,320 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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 org.apache.sling.scripting.core.impl.jsr223;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+
+import org.apache.sling.api.scripting.SlingScriptConstants;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.BundleListener;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Reference;
+import org.osgi.service.component.annotations.ReferenceCardinality;
+import org.osgi.service.component.annotations.ReferencePolicy;
+import org.osgi.service.component.annotations.ReferencePolicyOption;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+ service = {ScriptEngineManager.class, SlingScriptEngineManager.class},
+ reference = @Reference(
+ name = "ScriptEngineFactory",
+ bind = "bindScriptEngineFactory",
+ unbind = "unbindScriptEngineFactory",
+ service = ScriptEngineFactory.class,
+ cardinality = ReferenceCardinality.MULTIPLE,
+ policy = ReferencePolicy.DYNAMIC
+ )
+)
+public class SlingScriptEngineManager extends ScriptEngineManager implements BundleListener {
+
+ public static final String EVENT_TOPIC_SCRIPT_MANAGER_UPDATED =
+ "org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManager/UPDATED";
+ public static final String ENGINE_FACTORY_SERVICE = "META-INF/services/" + ScriptEngineFactory.class.getName();
+
+ private static final Logger LOG = LoggerFactory.getLogger(SlingScriptEngineManager.class);
+
+ private final Set<Bundle> engineSpiBundles = new HashSet<>();
+ private final ReentrantReadWriteLock readWriteLock = new ReentrantReadWriteLock();
+ private final Map<ScriptEngineFactory, Map<String, Object>> factoriesProperties = new HashMap<>();
+ private final Set<ServiceReference<ScriptEngineFactory>> serviceReferences = new HashSet<>();
+
+ private ScriptEngineManager internalManager = new ScriptEngineManager(SlingScriptEngineManager.class.getClassLoader());
+ private SortedSet<SortableScriptEngineFactory> factories = new TreeSet<>();
+ private ComponentContext componentContext;
+
+ @Reference(policy = ReferencePolicy.DYNAMIC,
+ policyOption = ReferencePolicyOption.GREEDY,
+ cardinality = ReferenceCardinality.OPTIONAL)
+ private volatile EventAdmin eventAdmin;
+
+ @Override
+ public ScriptEngine getEngineByName(String shortName) {
+ readWriteLock.readLock().lock();
+ try {
+ return internalManager.getEngineByName(shortName);
+ } finally {
+ readWriteLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public ScriptEngine getEngineByExtension(String extension) {
+ readWriteLock.readLock().lock();
+ try {
+ return internalManager.getEngineByExtension(extension);
+ } finally {
+ readWriteLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public ScriptEngine getEngineByMimeType(String mimeType) {
+ readWriteLock.readLock().lock();
+ try {
+ return internalManager.getEngineByMimeType(mimeType);
+ } finally {
+ readWriteLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public List<ScriptEngineFactory> getEngineFactories() {
+ readWriteLock.readLock().lock();
+ try {
+ ArrayList<ScriptEngineFactory> list = new ArrayList<>(factories.size());
+ list.addAll(factories);
+ return Collections.unmodifiableList(list);
+ } finally {
+ readWriteLock.readLock().unlock();
+ }
+ }
+
+ @Override
+ public void registerEngineName(String name, ScriptEngineFactory factory) {
+ readWriteLock.writeLock().lock();
+ try {
+ internalManager.registerEngineName(name, factory);
+ } finally {
+ readWriteLock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void registerEngineMimeType(String type, ScriptEngineFactory factory) {
+ readWriteLock.writeLock().lock();
+ try {
+ internalManager.registerEngineMimeType(type, factory);
+ } finally {
+ readWriteLock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void registerEngineExtension(String extension, ScriptEngineFactory factory) {
+ readWriteLock.writeLock().lock();
+ try {
+ internalManager.registerEngineExtension(extension, factory);
+ } finally {
+ readWriteLock.writeLock().unlock();
+ }
+ }
+
+ @Override
+ public void bundleChanged(BundleEvent event) {
+ if (event.getType() == BundleEvent.STARTED
+ && event.getBundle().getEntry(ENGINE_FACTORY_SERVICE) != null) {
+ synchronized (this.engineSpiBundles) {
+ this.engineSpiBundles.add(event.getBundle());
+ }
+ updateFactories();
+ } else if (event.getType() == BundleEvent.STOPPED) {
+ boolean refresh;
+ synchronized (this.engineSpiBundles) {
+ refresh = this.engineSpiBundles.remove(event.getBundle());
+ }
+ if (refresh) {
+ updateFactories();
+ }
+ }
+ }
+
+ public Map<String, Object> getProperties(ScriptEngineFactory factory) {
+ readWriteLock.readLock().lock();
+ try {
+ return factoriesProperties.get(factory);
+ } finally {
+ readWriteLock.readLock().unlock();
+ }
+ }
+
+ @Activate
+ private void activate(ComponentContext componentContext) {
+ this.componentContext = componentContext;
+ updateFactories();
+ }
+
+ private void bindScriptEngineFactory(final ServiceReference<ScriptEngineFactory> serviceReference,
+ final ScriptEngineFactory factory) {
+ synchronized (this.serviceReferences) {
+ serviceReferences.add(serviceReference);
+ }
+ updateFactories();
+ postEvent(SlingScriptConstants.TOPIC_SCRIPT_ENGINE_FACTORY_ADDED, factory);
+ }
+
+ private void unbindScriptEngineFactory(final ServiceReference<ScriptEngineFactory> serviceReference, final ScriptEngineFactory
+ factory) {
+ synchronized (this.serviceReferences) {
+ serviceReferences.remove(serviceReference);
+ if (componentContext != null) {
+ componentContext.getBundleContext().ungetService(serviceReference);
+ }
+ }
+ updateFactories();
+ postEvent(SlingScriptConstants.TOPIC_SCRIPT_ENGINE_FACTORY_REMOVED, factory);
+ }
+
+ private void updateFactories() {
+ readWriteLock.writeLock().lock();
+ try {
+ factories = new TreeSet<>();
+ internalManager = new ScriptEngineManager(SlingScriptEngineManager.class.getClassLoader());
+ long fakeBundleIdCounter = Long.MIN_VALUE;
+ // first add the platform factories
+ for (ScriptEngineFactory factory : internalManager.getEngineFactories()) {
+ SortableScriptEngineFactory ssef = new SortableScriptEngineFactory(factory, fakeBundleIdCounter++, 0);
+ factories.add(ssef);
+ }
+ // then factories from SPI Bundles
+ for (Bundle bundle : engineSpiBundles) {
+ URL url = bundle.getEntry(ENGINE_FACTORY_SERVICE);
+ InputStream ins = null;
+ try {
+ ins = url.openStream();
+ BufferedReader reader = new BufferedReader(new InputStreamReader(ins, StandardCharsets.UTF_8));
+ String line;
+ while ((line = reader.readLine()) != null) {
+ if (!line.startsWith("#") && line.trim().length() > 0) {
+ try {
+ Class<ScriptEngineFactory> clazz = (Class<ScriptEngineFactory>) bundle.loadClass(line);
+ SortableScriptEngineFactory ssef = new SortableScriptEngineFactory(clazz.getDeclaredConstructor()
+ .newInstance(), fakeBundleIdCounter++, 0);
+ factories.add(ssef);
+ } catch (Throwable t) {
+ LOG.error("Cannot register ScriptEngineFactory " + line, t);
+ }
+ }
+ }
+ } catch (IOException ioe) {
+ LOG.error("Unable to process bundle " + bundle.getSymbolicName(), ioe);
+ } finally {
+ if (ins != null) {
+ try {
+ ins.close();
+ } catch (IOException ioe) {
+ LOG.error("Unable to release stream resource.", ioe);
+ }
+ }
+ }
+ }
+ // and finally factories registered as OSGi services
+ if (componentContext != null) {
+ factoriesProperties.clear();
+ for (ServiceReference<ScriptEngineFactory> serviceReference : serviceReferences) {
+ ScriptEngineFactory scriptEngineFactory = componentContext.getBundleContext().getService(serviceReference);
+ SortableScriptEngineFactory sortableScriptEngineFactory =
+ new SortableScriptEngineFactory(scriptEngineFactory, serviceReference.getBundle().getBundleId(),
+ PropertiesUtil.toInteger(serviceReference.getProperty(Constants.SERVICE_RANKING), 0));
+ factories.add(sortableScriptEngineFactory);
+ Map<String, Object> factoryProperties = new HashMap<>(serviceReference.getPropertyKeys().length);
+ for (String key : serviceReference.getPropertyKeys()) {
+ factoryProperties.put(key, serviceReference.getProperty(key));
+ }
+ factoriesProperties.put(scriptEngineFactory, factoryProperties);
+ }
+ }
+ // register the associations at the end, so that the priority sorting is taken into consideration
+ for (ScriptEngineFactory factory : factories) {
+ registerAssociations(factory);
+ }
+ if (eventAdmin != null) {
+ eventAdmin.postEvent(new Event(EVENT_TOPIC_SCRIPT_MANAGER_UPDATED, Collections.EMPTY_MAP));
+ }
+ } finally {
+ readWriteLock.writeLock().unlock();
+ }
+ }
+
+ private void registerAssociations(ScriptEngineFactory factory) {
+ for (String extension : factory.getExtensions()) {
+ internalManager.registerEngineExtension(extension, factory);
+ }
+ for (String mimeType : factory.getMimeTypes()) {
+ internalManager.registerEngineMimeType(mimeType, factory);
+ }
+ for (String name : factory.getNames()) {
+ internalManager.registerEngineName(name, factory);
+ }
+ }
+
+ private void postEvent(final String topic, final ScriptEngineFactory scriptEngineFactory) {
+ if (eventAdmin != null) {
+ final Dictionary<String, Object> props = new Hashtable<>();
+ props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_NAME, scriptEngineFactory.getEngineName());
+ props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_VERSION, scriptEngineFactory.getEngineVersion());
+ props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_EXTENSIONS, scriptEngineFactory.getExtensions().toArray(new
+ String[0]));
+ props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_LANGUAGE_NAME, scriptEngineFactory.getLanguageName());
+ props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_LANGUAGE_VERSION, scriptEngineFactory.getLanguageVersion());
+ props.put(SlingScriptConstants.PROPERTY_SCRIPT_ENGINE_FACTORY_MIME_TYPES, scriptEngineFactory.getMimeTypes().toArray(new
+ String[0]));
+ eventAdmin.postEvent(new Event(topic, props));
+ }
+ }
+}
diff --git a/src/main/java/org/apache/sling/scripting/core/impl/jsr223/SortableScriptEngineFactory.java b/src/main/java/org/apache/sling/scripting/core/impl/jsr223/SortableScriptEngineFactory.java
new file mode 100644
index 0000000..b04573f
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/core/impl/jsr223/SortableScriptEngineFactory.java
@@ -0,0 +1,134 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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 org.apache.sling.scripting.core.impl.jsr223;
+
+import java.util.List;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+public class SortableScriptEngineFactory implements ScriptEngineFactory, Comparable {
+
+ private final ScriptEngineFactory delegate;
+ private final int serviceRanking;
+ private final long bundleId;
+
+ /**
+ * Constructor for implicit {@link ScriptEngineFactory} provided by the platform.
+ *
+ * @param delegate the actual {@link ScriptEngineFactory}
+ */
+ SortableScriptEngineFactory(ScriptEngineFactory delegate) {
+ this.delegate = delegate;
+ serviceRanking = 0;
+ bundleId = 0;
+ }
+
+ /**
+ * Constructor for OSGi registered {@link ScriptEngineFactory} instances.
+ *
+ * @param delegate the actual {@link ScriptEngineFactory}
+ * @param bundleId the bundle id of the bundle registering the {@link ScriptEngineFactory}
+ * @param serviceRanking the service ranking of the {@link ScriptEngineFactory}
+ */
+ SortableScriptEngineFactory(ScriptEngineFactory delegate, long bundleId, int serviceRanking) {
+ this.delegate = delegate;
+ this.bundleId = bundleId;
+ this.serviceRanking = serviceRanking;
+ }
+
+ @Override
+ public String getEngineName() {
+ return delegate.getEngineName();
+ }
+
+ @Override
+ public String getEngineVersion() {
+ return delegate.getEngineVersion();
+ }
+
+ @Override
+ public List<String> getExtensions() {
+ return delegate.getExtensions();
+ }
+
+ @Override
+ public List<String> getMimeTypes() {
+ return delegate.getMimeTypes();
+ }
+
+ @Override
+ public List<String> getNames() {
+ return delegate.getNames();
+ }
+
+ @Override
+ public String getLanguageName() {
+ return delegate.getLanguageName();
+ }
+
+ @Override
+ public String getLanguageVersion() {
+ return delegate.getLanguageVersion();
+ }
+
+ @Override
+ public Object getParameter(String key) {
+ return delegate.getParameter(key);
+ }
+
+ @Override
+ public String getMethodCallSyntax(String obj, String m, String... args) {
+ return delegate.getMethodCallSyntax(obj, m, args);
+ }
+
+ @Override
+ public String getOutputStatement(String toDisplay) {
+ return delegate.getOutputStatement(toDisplay);
+ }
+
+ @Override
+ public String getProgram(String... statements) {
+ return delegate.getProgram(statements);
+ }
+
+ @Override
+ public ScriptEngine getScriptEngine() {
+ return delegate.getScriptEngine();
+ }
+
+ @Override
+ public int compareTo(Object o) {
+ SortableScriptEngineFactory other = (SortableScriptEngineFactory) o;
+ if (equals(other)) {
+ return 0;
+ }
+ if (serviceRanking == other.serviceRanking) {
+ if (bundleId > other.bundleId) {
+ return 1;
+ } else if (bundleId == other.bundleId) {
+ return 0;
+ }
+ return -1;
+ } else if (serviceRanking > other.serviceRanking) {
+ return 1;
+ }
+ return -1;
+ }
+}
diff --git a/src/test/java/org/apache/sling/scripting/core/ScriptHelperTest.java b/src/test/java/org/apache/sling/scripting/core/ScriptHelperTest.java
index af578ec..646a3eb 100644
--- a/src/test/java/org/apache/sling/scripting/core/ScriptHelperTest.java
+++ b/src/test/java/org/apache/sling/scripting/core/ScriptHelperTest.java
@@ -26,7 +26,7 @@ import static org.junit.Assert.fail;
import java.util.Dictionary;
import java.util.Hashtable;
-import org.apache.sling.testing.mock.sling.junit.SlingContext;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -35,7 +35,7 @@ import org.osgi.framework.Constants;
public class ScriptHelperTest {
@Rule
- public SlingContext sling = new SlingContext();
+ public OsgiContext sling = new OsgiContext();
private ScriptHelper sh;
private final int [] RANKINGS = { 42, 62, -12, 76, -123, 0, 7432, -21 };
@@ -74,4 +74,4 @@ public class ScriptHelperTest {
assertEquals(RANKINGS.length, svc.length);
assertHigherRankingComesFirst(svc);
}
-}
\ No newline at end of file
+}
diff --git a/src/test/java/org/apache/sling/scripting/core/impl/ScriptEngineManagerFactoryTest.java b/src/test/java/org/apache/sling/scripting/core/impl/ScriptEngineManagerFactoryTest.java
deleted file mode 100644
index de8c85d..0000000
--- a/src/test/java/org/apache/sling/scripting/core/impl/ScriptEngineManagerFactoryTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * 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 org.apache.sling.scripting.core.impl;
-
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.util.Dictionary;
-
-import javax.script.ScriptEngineManager;
-
-import org.jmock.Expectations;
-import org.jmock.Mockery;
-import org.jmock.integration.junit4.JMock;
-import org.jmock.integration.junit4.JUnit4Mockery;
-import org.junit.Before;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.BundleEvent;
-import org.osgi.framework.BundleListener;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.component.ComponentContext;
-
-/**
- * Test of the ScriptEngineManagerFactory.
- */
-@RunWith(JMock.class)
-public class ScriptEngineManagerFactoryTest {
-
- private static Class<?> SCRIPT_ENGINE_FACTORY = DummyScriptEngineFactory.class;
-
- private Mockery context = new JUnit4Mockery();
-
- private ComponentContext componentCtx;
-
- private BundleContext bundleCtx;
-
- @Before
- public void setup() throws Exception {
- componentCtx = context.mock(ComponentContext.class);
- bundleCtx = context.mock(BundleContext.class);
- context.checking(new Expectations(){{
- atLeast(1).of(componentCtx).getBundleContext();
- will(returnValue(bundleCtx));
-
- allowing(bundleCtx).createFilter(with(any(String.class)));
- allowing(bundleCtx).addServiceListener(with(any(ServiceListener.class)));
- allowing(bundleCtx).addServiceListener(with(any(ServiceListener.class)), with(any(String.class)));
- allowing(bundleCtx).getServiceReferences(with(any(String.class)), with(aNull(String.class)));
- allowing(bundleCtx).getServiceReferences(with(aNull(String.class)), with(aNull(String.class)));
- allowing(bundleCtx).getServiceReferences(with(any(String.class)), with(any(String.class)));
- allowing(bundleCtx).getServiceReferences(with(aNull(String.class)), with(any(String.class)));
-
- one(bundleCtx).addBundleListener(with(any(BundleListener.class)));
- one(bundleCtx).getBundles();
- will(returnValue(new Bundle[0]));
-
- allowing(bundleCtx).registerService(with(equal("org.apache.sling.scripting.core.impl.ScriptEngineConsolePlugin")), with(any(Object.class)), with(any(Dictionary.class)));
- will(returnValue(new MockServiceRegistration()));
-
-
- }});
- }
-
-
- @Test
- public void checkNonNullManagerAfterActivate() throws Exception {
- context.checking(new Expectations(){{
- one(bundleCtx).registerService(with(equal(new String[] {"javax.script.ScriptEngineManager", "org.apache.sling.scripting.core.impl.helper.SlingScriptEngineManager"})), with(any(Object.class)), with(any(Dictionary.class)));
- will(returnValue(new MockServiceRegistration()));
- }});
-
- ScriptEngineManagerFactory factory = new ScriptEngineManagerFactory();
- factory.activate(componentCtx);
-
- assertNotNull(factory.getScriptEngineManager());
- }
-
- @Test
- public void checkAddingScriptBundle() throws Exception {
- context.checking(new Expectations(){{
- exactly(1).of(bundleCtx).registerService(with(equal(new String[] {"javax.script.ScriptEngineManager", "org.apache.sling.scripting.core.impl.helper.SlingScriptEngineManager"})), with(any(Object.class)), with(any(Dictionary.class)));
- will(returnValue(new MockServiceRegistration()));
- }});
-
- ScriptEngineManagerFactory factory = new ScriptEngineManagerFactory();
- factory.activate(componentCtx);
-
- ScriptEngineManager first = factory.getScriptEngineManager();
-
- assertNull(first.getEngineByName("dummy"));
-
- final Bundle bundle = context.mock(Bundle.class);
-
- final File factoryFile = createFactoryFile();
-
- context.checking(new Expectations() {{
-
- atLeast(1).of(bundle).getEntry("META-INF/services/javax.script.ScriptEngineFactory");
- will(returnValue(factoryFile.toURI().toURL()));
-
- atLeast(1).of(bundle).loadClass(SCRIPT_ENGINE_FACTORY.getName());
- will(returnValue(SCRIPT_ENGINE_FACTORY));
- }});
-
- factory.bundleChanged(new BundleEvent(BundleEvent.STARTED, bundle));
-
- ScriptEngineManager second = factory.getScriptEngineManager();
-
- assertNotNull(second.getEngineByName("dummy"));
- }
-
- private File createFactoryFile() throws IOException {
- File tempFile = File.createTempFile("scriptEngine", "tmp");
- tempFile.deleteOnExit();
-
- FileOutputStream fos = null;
- try {
- fos = new FileOutputStream(tempFile);
- fos.write("#I'am a test-comment\n".getBytes());
- fos.write(SCRIPT_ENGINE_FACTORY.getName().getBytes());
- } finally {
- if (fos != null) {
- fos.close();
- }
- }
- return tempFile;
- }
-
- private class MockServiceRegistration implements ServiceRegistration {
-
- public ServiceReference getReference() {
- throw new UnsupportedOperationException();
- }
-
- @SuppressWarnings("unchecked")
- public void setProperties(Dictionary properties) {
- // NO-OP
- }
-
- public void unregister() {
- // NO-OP
- }
-
- }
-
-}
diff --git a/src/test/java/org/apache/sling/scripting/core/impl/DummyScriptEngineFactory.java b/src/test/java/org/apache/sling/scripting/core/impl/jsr223/DummyScriptEngineFactory.java
similarity index 76%
rename from src/test/java/org/apache/sling/scripting/core/impl/DummyScriptEngineFactory.java
rename to src/test/java/org/apache/sling/scripting/core/impl/jsr223/DummyScriptEngineFactory.java
index 3c67591..9a36ecb 100644
--- a/src/test/java/org/apache/sling/scripting/core/impl/DummyScriptEngineFactory.java
+++ b/src/test/java/org/apache/sling/scripting/core/impl/jsr223/DummyScriptEngineFactory.java
@@ -1,20 +1,22 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with this
- * work for additional information regarding copyright ownership. The ASF
- * 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 org.apache.sling.scripting.core.impl;
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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 org.apache.sling.scripting.core.impl.jsr223;
import java.io.Reader;
import java.util.Arrays;
diff --git a/src/test/java/org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManagerTest.java b/src/test/java/org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManagerTest.java
new file mode 100644
index 0000000..a6df3c4
--- /dev/null
+++ b/src/test/java/org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManagerTest.java
@@ -0,0 +1,208 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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 org.apache.sling.scripting.core.impl.jsr223;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.mockito.invocation.InvocationOnMock;
+import org.mockito.stubbing.Answer;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SlingScriptEngineManagerTest {
+
+ private static Class<?> SCRIPT_ENGINE_FACTORY = DummyScriptEngineFactory.class;
+
+ @Rule
+ public final OsgiContext context = new OsgiContext();
+
+
+ @Before
+ public void setUp() {
+ context.registerInjectActivateService(new SlingScriptEngineManager());
+ }
+
+ @Test
+ public void testPlatformScriptEngines() {
+ ScriptEngineManager scriptEngineManager = context.getService(ScriptEngineManager.class);
+ assertNotNull("Expected a ScriptEngineManager would be already registered.", scriptEngineManager);
+ assertEquals("The ScriptEngineManager should have had 1 ScriptEngineFactory registered.", 1, scriptEngineManager
+ .getEngineFactories().size());
+ }
+
+ @Test
+ public void testOSGiRegisteredFactoriesDifferentServiceRanking() throws Exception {
+ int expectedEvents = 3;
+ CountDownLatch latch = new CountDownLatch(expectedEvents);
+ TestEventHandler eventHandler = new TestEventHandler
+ (latch, "org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManager/UPDATED");
+ context.registerService(
+ EventHandler.class, eventHandler,
+ new HashMap<String, Object>() {{
+ put(EventConstants.EVENT_TOPIC, "org/apache/sling/scripting/core/impl/jsr223/SlingScriptEngineManager/*");
+ }}
+ );
+
+ ScriptEngineFactory f1 = mockScriptEngineFactory("f1", "1.0", Collections.singletonList("f1"), "f1", "1.0", Collections
+ .singletonList("text"));
+ ScriptEngineFactory f2 = mockScriptEngineFactory("f2", "1.0", Collections.singletonList("f2"), "f2", "1.0", Collections
+ .singletonList("text"));
+
+ ServiceRegistration<ScriptEngineFactory> f1SR = context.bundleContext().registerService(ScriptEngineFactory.class, f1, new
+ Hashtable<String, Object>() {{
+ put(Constants.SERVICE_RANKING, 2);
+ }});
+ context.bundleContext().registerService(ScriptEngineFactory.class, f2, new
+ Hashtable<String, Object>() {{
+ put(Constants.SERVICE_RANKING, 1);
+ }});
+
+ ScriptEngineManager scriptEngineManager = context.getService(ScriptEngineManager.class);
+ assertNotNull("Expected a ScriptEngineManager would be already registered.", scriptEngineManager);
+ List<ScriptEngineFactory> factories = scriptEngineManager.getEngineFactories();
+ assertEquals("The ScriptEngineManager should have had 3 ScriptEngineFactories registered.", 3, factories.size());
+ assertEquals(f1.getEngineName(), factories.get(2).getEngineName());
+ assertEquals(f2.getEngineName(), factories.get(1).getEngineName());
+
+ SlingScriptEngineManager slingScriptEngineManager = context.getService(SlingScriptEngineManager.class);
+ assertEquals(2, slingScriptEngineManager.getProperties(f1).get(Constants.SERVICE_RANKING));
+
+ f1SR.unregister();
+
+ factories = scriptEngineManager.getEngineFactories();
+ assertEquals("The ScriptEngineManager should have had 2 ScriptEngineFactories registered.", 2, factories.size());
+ assertEquals(f2.getEngineName(), factories.get(1).getEngineName());
+
+ assertEquals(f2, scriptEngineManager.getEngineByName("f2").getFactory());
+ assertEquals(f2, scriptEngineManager.getEngineByExtension("f2").getFactory());
+ assertEquals(f2, scriptEngineManager.getEngineByMimeType("text").getFactory());
+
+ latch.await(2, TimeUnit.SECONDS);
+ assertEquals("Expected a different number of processed " + SlingScriptEngineManager.EVENT_TOPIC_SCRIPT_MANAGER_UPDATED + " events.",
+ expectedEvents, eventHandler.processedEvents);
+ }
+
+ @Test
+ public void testBundledScriptEngineFactory() throws Exception {
+ URL url = createFactoryFile().toURI().toURL();
+ Bundle bundle = mock(Bundle.class);
+ when(bundle.getEntry(SlingScriptEngineManager.ENGINE_FACTORY_SERVICE)).thenReturn(url);
+ when(bundle.loadClass(SCRIPT_ENGINE_FACTORY.getName())).thenAnswer(new Answer<Class>() {
+ @Override
+ public Class answer(InvocationOnMock invocation) {
+ return SCRIPT_ENGINE_FACTORY;
+ }
+ });
+
+ BundleEvent bundleEvent = new BundleEvent(BundleEvent.STARTED, bundle);
+ SlingScriptEngineManager slingScriptEngineManager = context.getService(SlingScriptEngineManager.class);
+ assertNotNull("Expected that the SlingScriptEngineManager would already be registered.", slingScriptEngineManager);
+ slingScriptEngineManager.bundleChanged(bundleEvent);
+ List<ScriptEngineFactory> factories = slingScriptEngineManager.getEngineFactories();
+ assertEquals("Expected 2 ScriptEngineFactories.", 2, factories.size());
+ assertEquals("Dummy Scripting Engine", factories.get(1).getEngineName());
+
+ bundleEvent = new BundleEvent(BundleEvent.STOPPED, bundle);
+ slingScriptEngineManager.bundleChanged(bundleEvent);
+ factories = slingScriptEngineManager.getEngineFactories();
+ assertEquals("Expected 1 ScriptEngineFactory.", 1, factories.size());
+ assertEquals("Oracle Nashorn", factories.get(0).getEngineName());
+ }
+
+ private ScriptEngineFactory mockScriptEngineFactory(String engineName, String engineVersion, List<String> extensions, String
+ languageName, String languageVersion, List<String> mimeTypes) {
+ ScriptEngineFactory factory = mock(ScriptEngineFactory.class);
+ when(factory.getEngineName()).thenReturn(engineName);
+ when(factory.getNames()).thenReturn(Collections.singletonList(engineName));
+ when(factory.getEngineVersion()).thenReturn(engineVersion);
+ when(factory.getExtensions()).thenReturn(extensions);
+ when(factory.getLanguageName()).thenReturn(languageName);
+ when(factory.getLanguageVersion()).thenReturn(languageVersion);
+ when(factory.getMimeTypes()).thenReturn(mimeTypes);
+ ScriptEngine scriptEngine = mock(ScriptEngine.class);
+ when(factory.getScriptEngine()).thenReturn(scriptEngine);
+ when(scriptEngine.getFactory()).thenReturn(factory);
+ return factory;
+ }
+
+ private File createFactoryFile() throws IOException {
+ File tempFile = File.createTempFile("scriptEngine", "tmp");
+ tempFile.deleteOnExit();
+
+ FileOutputStream fos = null;
+ try {
+ fos = new FileOutputStream(tempFile);
+ fos.write("#I'm a test-comment\n".getBytes());
+ fos.write(SCRIPT_ENGINE_FACTORY.getName().getBytes());
+ } finally {
+ if (fos != null) {
+ fos.close();
+ }
+ }
+ return tempFile;
+ }
+
+
+ private static class TestEventHandler implements EventHandler {
+
+ String topic;
+ CountDownLatch latch;
+ int processedEvents = 0;
+
+ public TestEventHandler(CountDownLatch latch, String topic) {
+ this.topic = topic;
+ this.latch = latch;
+ }
+
+ @Override
+ public void handleEvent(Event event) {
+ if (event.getTopic().equals(topic)) {
+ processedEvents++;
+ latch.countDown();
+ }
+ }
+ }
+}
diff --git a/src/test/java/org/apache/sling/scripting/core/impl/jsr223/SortableScriptEngineFactoryTest.java b/src/test/java/org/apache/sling/scripting/core/impl/jsr223/SortableScriptEngineFactoryTest.java
new file mode 100644
index 0000000..e220bcf
--- /dev/null
+++ b/src/test/java/org/apache/sling/scripting/core/impl/jsr223/SortableScriptEngineFactoryTest.java
@@ -0,0 +1,174 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one
+ ~ or more contributor license agreements. See the NOTICE file
+ ~ distributed with this work for additional information
+ ~ regarding copyright ownership. The ASF 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 org.apache.sling.scripting.core.impl.jsr223;
+
+import java.util.Collections;
+import java.util.List;
+
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class SortableScriptEngineFactoryTest {
+
+ @Test
+ public void testDelegateConstructor() {
+ ScriptEngineFactory delegate = mock(ScriptEngineFactory.class);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(delegate);
+ assertEquals(0, sortableScriptEngineFactory.compareTo(getCompareFactory(0, 0)));
+ }
+
+ @Test
+ public void getEngineName() {
+ String answer = "answer";
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getEngineName()).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getEngineName());
+ }
+
+ @Test
+ public void getEngineVersion() {
+ String answer = "answer";
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getEngineVersion()).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getEngineVersion());
+ }
+
+ @Test
+ public void getExtensions() {
+ List<String> answer = Collections.emptyList();
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getExtensions()).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getExtensions());
+ }
+
+ @Test
+ public void getMimeTypes() {
+ List<String> answer = Collections.emptyList();
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getMimeTypes()).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getMimeTypes());
+ }
+
+ @Test
+ public void getNames() {
+ List<String> answer = Collections.emptyList();
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getNames()).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getNames());
+ }
+
+ @Test
+ public void getLanguageName() {
+ String answer = "answer";
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getLanguageName()).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getLanguageName());
+ }
+
+ @Test
+ public void getLanguageVersion() {
+ String answer = "answer";
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getLanguageVersion()).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getLanguageVersion());
+ }
+
+ @Test
+ public void getParameter() {
+ String answer = "answer";
+ String key = "key";
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getParameter(key)).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getParameter(key));
+ }
+
+ @Test
+ public void getMethodCallSyntax() {
+ String answer = "answer";
+ String obj = "obj";
+ String m = "m";
+ String[] args = new String[0];
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getMethodCallSyntax(obj, m, args)).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getMethodCallSyntax(obj, m, args));
+ }
+
+ @Test
+ public void getOutputStatement() {
+ String answer = "answer";
+ String toDisplay = "toDisplay";
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getOutputStatement(toDisplay)).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getOutputStatement(toDisplay));
+ }
+
+ @Test
+ public void getProgram() {
+ String answer = "answer";
+ String[] statements = new String[0];
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getProgram(statements)).thenReturn(answer);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(answer, sortableScriptEngineFactory.getProgram(statements));
+ }
+
+ @Test
+ public void getScriptEngine() {
+ ScriptEngine scriptEngine = mock(ScriptEngine.class);
+ ScriptEngineFactory scriptEngineFactory = mock(ScriptEngineFactory.class);
+ when(scriptEngineFactory.getScriptEngine()).thenReturn(scriptEngine);
+ SortableScriptEngineFactory sortableScriptEngineFactory = new SortableScriptEngineFactory(scriptEngineFactory, 0, 0);
+ assertEquals(scriptEngine, sortableScriptEngineFactory.getScriptEngine());
+ }
+
+ @Test
+ public void compareTo() {
+ SortableScriptEngineFactory same = getCompareFactory(1, 2);
+ assertEquals(0, same.compareTo(same));
+ assertEquals(0, getCompareFactory(0, 0).compareTo(getCompareFactory(0, 0)));
+ assertEquals(1, getCompareFactory(1, 0).compareTo(getCompareFactory(0, 0)));
+ assertEquals(1, getCompareFactory(0, 1).compareTo(getCompareFactory(0, 0)));
+ assertEquals(1, getCompareFactory(1, 1).compareTo(getCompareFactory(1, 0)));
+ assertEquals(1, getCompareFactory(1, 1).compareTo(getCompareFactory(0, 1)));
+ assertEquals(-1, getCompareFactory(0, 0).compareTo(getCompareFactory(1, 0)));
+ assertEquals(-1, getCompareFactory(0, 0).compareTo(getCompareFactory(0, 1)));
+ assertEquals(-1, getCompareFactory(0, 1).compareTo(getCompareFactory(1, 1)));
+ assertEquals(-1, getCompareFactory(0, 0).compareTo(getCompareFactory(0, 1)));
+ }
+
+ private SortableScriptEngineFactory getCompareFactory(long bundleId, int serviceRanking) {
+ return new SortableScriptEngineFactory(null, bundleId, serviceRanking);
+ }
+}
diff --git a/src/test/java/org/apache/sling/scripting/core/it/ScriptingCoreTestSupport.java b/src/test/java/org/apache/sling/scripting/core/it/ScriptingCoreTestSupport.java
index a5b90da..7f35c79 100644
--- a/src/test/java/org/apache/sling/scripting/core/it/ScriptingCoreTestSupport.java
+++ b/src/test/java/org/apache/sling/scripting/core/it/ScriptingCoreTestSupport.java
@@ -18,6 +18,8 @@
*/
package org.apache.sling.scripting.core.it;
+import java.util.Arrays;
+
import org.apache.sling.testing.paxexam.TestSupport;
import org.ops4j.pax.exam.Configuration;
import org.ops4j.pax.exam.Option;
@@ -28,6 +30,7 @@ import static org.apache.sling.testing.paxexam.SlingOptions.webconsole;
import static org.ops4j.pax.exam.CoreOptions.composite;
import static org.ops4j.pax.exam.CoreOptions.junitBundles;
import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.vmOption;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.factoryConfiguration;
import static org.ops4j.pax.exam.cm.ConfigurationAdminOptions.newConfiguration;
@@ -35,7 +38,7 @@ public class ScriptingCoreTestSupport extends TestSupport {
@Configuration
public Option[] configuration() {
- return new Option[]{
+ Option[] configuration = new Option[]{
baseConfiguration(),
launchpad(),
// Sling Scripting Core
@@ -52,6 +55,17 @@ public class ScriptingCoreTestSupport extends TestSupport {
// testing
junitBundles()
};
+ try {
+ Integer javaVersion = Integer.parseInt(System.getProperty("java.specification.version"));
+ if (javaVersion >= 9) {
+ Option[] java9AndBeyondConfiguration = Arrays.copyOf(configuration, configuration.length + 1);
+ java9AndBeyondConfiguration[java9AndBeyondConfiguration.length - 1] = vmOption("--add-modules=java.se.ee");
+ configuration = java9AndBeyondConfiguration;
+ }
+ } catch (NumberFormatException e) {
+ // ignore
+ }
+ return configuration;
}
protected Option launchpad() {
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.