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 2020/03/09 21:04:05 UTC

[sling-org-apache-sling-scripting-bundle-tracker] branch master updated: SLING-9182 - The Scripting Bundle Tracker should require bundles to provide information about the needed Script Engines

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

radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-bundle-tracker.git


The following commit(s) were added to refs/heads/master by this push:
     new ac7d153  SLING-9182 - The Scripting Bundle Tracker should require bundles to provide information about the needed Script Engines
ac7d153 is described below

commit ac7d153cdaadcb3e99285a5b0f5b5f4431597ae2
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Mar 9 22:02:35 2020 +0100

    SLING-9182 - The Scripting Bundle Tracker should require bundles to provide information about the needed Script Engines
    
    * scripts or precompiled units are only executed if the bundles provide a
    sling.resourceType;scriptEngine attribute whose value identifies a script
    engine installed on the platform
---
 .../tracker/internal/BundledScriptFinder.java      | 82 ++++++++++++++++++----
 .../tracker/internal/BundledScriptServlet.java     |  4 +-
 .../tracker/internal/BundledScriptTracker.java     | 18 ++---
 .../tracker/internal/ResourceTypeParser.java       |  5 ++
 .../bundle/tracker/internal/TypeProvider.java      | 18 ++---
 5 files changed, 93 insertions(+), 34 deletions(-)

diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
index 0bc350d..a5a3c82 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptFinder.java
@@ -25,14 +25,22 @@ import java.util.Collections;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
 import java.util.List;
+import java.util.Map;
 import java.util.Set;
 
+import javax.script.ScriptEngine;
 import javax.script.ScriptEngineFactory;
 import javax.script.ScriptEngineManager;
 
 import org.apache.commons.lang3.StringUtils;
 import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.servlets.ServletResolverConstants;
 import org.apache.sling.commons.compiler.source.JavaEscapeHelper;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Version;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleWiring;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 
@@ -52,15 +60,16 @@ public class BundledScriptFinder {
     Executable getScript(SlingHttpServletRequest request, LinkedHashSet<TypeProvider> typeProviders, boolean precompiledScripts) {
         List<String> scriptMatches;
         for (TypeProvider provider : typeProviders) {
-            scriptMatches = buildScriptMatches(request, provider.getType());
-            for (String match : scriptMatches) {
-                for (String extension : getScriptEngineExtensions()) {
+            scriptMatches = buildScriptMatches(request, provider.getResourceType());
+            String scriptEngineName = getScriptEngineName(request, provider);
+            if (StringUtils.isNotEmpty(scriptEngineName)) {
+                for (String match : scriptMatches) {
                     URL bundledScriptURL;
                     if (precompiledScripts) {
                         String className = JavaEscapeHelper.makeJavaPackage(match);
                         try {
                             Class clazz = provider.getBundle().loadClass(className);
-                            return new PrecompiledScript(provider.getBundle(), scriptEngineManager.getEngineByExtension(extension),
+                            return new PrecompiledScript(provider.getBundle(), scriptEngineManager.getEngineByName(scriptEngineName),
                                     clazz.getDeclaredConstructor().newInstance());
                         } catch (ClassNotFoundException e) {
                             // do nothing here
@@ -68,9 +77,26 @@ public class BundledScriptFinder {
                             throw new RuntimeException("Cannot correctly instantiate class " + className + ".");
                         }
                     } else {
-                        bundledScriptURL = provider.getBundle().getEntry(NS_JAVAX_SCRIPT_CAPABILITY + SLASH + match + DOT + extension);
-                        if (bundledScriptURL != null) {
-                            return new Script(provider.getBundle(), bundledScriptURL, scriptEngineManager.getEngineByExtension(extension));
+                        ScriptEngine scriptEngine = null;
+                        List<String> scriptEngineExtensions = Collections.emptyList();
+                        for (ScriptEngineFactory factory : scriptEngineManager.getEngineFactories()) {
+                            for (String shortName : factory.getNames()) {
+                                if (shortName.equals(scriptEngineName)) {
+                                    scriptEngine = factory.getScriptEngine();
+                                    scriptEngineExtensions = factory.getExtensions();
+                                    break;
+                                }
+                            }
+                        }
+                        if (scriptEngine != null) {
+                            for (String scriptEngineExtension : scriptEngineExtensions) {
+                                bundledScriptURL =
+                                        provider.getBundle()
+                                                .getEntry(NS_JAVAX_SCRIPT_CAPABILITY + SLASH + match + DOT + scriptEngineExtension);
+                                if (bundledScriptURL != null) {
+                                    return new Script(provider.getBundle(), bundledScriptURL, scriptEngine);
+                                }
+                            }
                         }
                     }
                 }
@@ -79,11 +105,10 @@ public class BundledScriptFinder {
         return null;
     }
 
-    private List<String> buildScriptMatches(SlingHttpServletRequest request, String providerType) {
+    private List<String> buildScriptMatches(SlingHttpServletRequest request, ResourceTypeParser.ResourceType resourceType) {
         List<String> matches = new ArrayList<>();
         String method = request.getMethod();
         boolean defaultMethod = DEFAULT_METHODS.contains(method);
-        ResourceTypeParser.ResourceType resourceType = ResourceTypeParser.parseResourceType(providerType);
         String extension = request.getRequestPathInfo().getExtension();
         String[] selectors = request.getRequestPathInfo().getSelectors();
         if (selectors.length > 0) {
@@ -125,12 +150,39 @@ public class BundledScriptFinder {
         return Collections.unmodifiableList(matches);
     }
 
-    private List<String> getScriptEngineExtensions() {
-        List<String> _scriptEngineExtensions = new ArrayList<>();
-        for (ScriptEngineFactory factory : scriptEngineManager.getEngineFactories()) {
-            _scriptEngineExtensions.addAll(factory.getExtensions());
+    private String getScriptEngineName(SlingHttpServletRequest request, TypeProvider typeProvider) {
+        String scriptEngineName = null;
+        Bundle bundle = typeProvider.getBundle();
+        BundleWiring bundleWiring = bundle.adapt(BundleWiring.class);
+        List<BundleCapability> capabilities = bundleWiring.getCapabilities(BundledScriptTracker.NS_SLING_RESOURCE_TYPE);
+        String[] selectors = request.getRequestPathInfo().getSelectors();
+        String requestExtension = request.getRequestPathInfo().getExtension();
+        String requestMethod = request.getMethod();
+        for (BundleCapability capability : capabilities) {
+            Map<String, Object> attributes = capability.getAttributes();
+            if (typeProvider.getResourceType().getType().equals(attributes.get(BundledScriptTracker.NS_SLING_RESOURCE_TYPE)) && Arrays.equals(selectors,
+                    PropertiesUtil.toStringArray(attributes.get(BundledScriptTracker.AT_SLING_SELECTORS), new String[]{}))) {
+                String version = typeProvider.getResourceType().getVersion();
+                Version capabilityVersion = (Version) attributes.get(BundledScriptTracker.AT_VERSION);
+                if (version != null && capabilityVersion!= null && !version.equals(capabilityVersion.toString())) {
+                    continue;
+                }
+                Set<String> capabilityRequestExtensions = new HashSet<>(
+                        Arrays.asList(PropertiesUtil.toStringArray(attributes.get(BundledScriptTracker.AT_SLING_EXTENSIONS), new String[0]))
+                );
+                Set<String> capabilityRequestMethods = new HashSet<>(
+                        Arrays.asList(
+                                PropertiesUtil.toStringArray(attributes.get(ServletResolverConstants.SLING_SERVLET_METHODS), new String[0]))
+                );
+                if (
+                    ((capabilityRequestExtensions.isEmpty() && "html".equals(requestExtension)) || capabilityRequestExtensions.contains(requestExtension)) &&
+                    ((capabilityRequestMethods.isEmpty() && ("GET".equals(requestMethod) || "HEAD".equals(requestMethod))) || capabilityRequestMethods.contains(requestMethod)) &&
+                    StringUtils.isEmpty(scriptEngineName)
+                ) {
+                    scriptEngineName = (String) attributes.get(BundledScriptTracker.AT_SCRIPT_ENGINE);
+                }
+            }
         }
-        Collections.reverse(_scriptEngineExtensions);
-        return Collections.unmodifiableList(_scriptEngineExtensions);
+        return scriptEngineName;
     }
 }
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
index 9555dae..8d8a0e1 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptServlet.java
@@ -97,8 +97,8 @@ class BundledScriptServlet extends GenericServlet {
                                 scriptsMap.put(scriptsMapKey, executable);
                             }
                         }
-                        lock.readLock().lock();
                     } finally {
+                        lock.readLock().lock();
                         lock.writeLock().unlock();
                     }
                 }
@@ -108,7 +108,7 @@ class BundledScriptServlet extends GenericServlet {
             if (executable != null) {
                 Set<String> wiredResourceTypes = new HashSet<>();
                 for (TypeProvider typeProvider : m_wiredTypeProviders) {
-                    wiredResourceTypes.add(typeProvider.getType());
+                    wiredResourceTypes.add(typeProvider.getResourceType().toString());
                 }
                 RequestWrapper requestWrapper = new RequestWrapper(request, wiredResourceTypes);
                 ScriptContext scriptContext = m_scriptContextProvider.prepareScriptContext(requestWrapper, response, executable);
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
index b4841e5..1d69b3a 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/BundledScriptTracker.java
@@ -82,10 +82,11 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
 
     static final String NS_SLING_RESOURCE_TYPE = "sling.resourceType";
     private static final Logger LOGGER = LoggerFactory.getLogger(BundledScriptTracker.class);
-    private static final String AT_SLING_SELECTORS = "sling.resourceType.selectors";
-    private static final String AT_SLING_EXTENSIONS = "sling.resourceType.extensions";
+    static final String AT_SLING_SELECTORS = "sling.resourceType.selectors";
+    static final String AT_SLING_EXTENSIONS = "sling.resourceType.extensions";
     private static final String REGISTERING_BUNDLE = "org.apache.sling.scripting.bundle.tracker.internal.BundledScriptTracker.registering_bundle";
     static final String AT_VERSION = "version";
+    static final String AT_SCRIPT_ENGINE = "scriptEngine";
     private static final String AT_EXTENDS = "extends";
 
     @Reference
@@ -170,8 +171,8 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
 
                     List<ServiceRegistration<Servlet>> regs = new ArrayList<>();
                     LinkedHashSet<TypeProvider> wiredProviders = new LinkedHashSet<>();
-                    wiredProviders.add(new TypeProvider(resourceType, bundle));
-                    wiredProviders.add(new TypeProvider(resourceTypeString, bundle));
+                    wiredProviders.add(new TypeProvider(ResourceTypeParser.parseResourceType(resourceType), bundle));
+                    wiredProviders.add(new TypeProvider(ResourceTypeParser.parseResourceType(resourceTypeString), bundle));
                     if (optionalWire.isPresent()) {
                         BundleWire extendsWire = optionalWire.get();
                         Bundle providerBundle = extendsWire.getProvider().getBundle();
@@ -180,8 +181,8 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                         Version wireResourceTypeVersion = (Version) wireCapabilityAttributes.get(AT_VERSION);
                         String wireResourceTypeString = wireResourceType + (wireResourceTypeVersion != null ? "/" +
                                 wireResourceTypeVersion.toString() : "");
-                        wiredProviders.add(new TypeProvider(wireResourceType, providerBundle));
-                        wiredProviders.add(new TypeProvider(wireResourceTypeString, providerBundle));
+                        wiredProviders.add(new TypeProvider(ResourceTypeParser.parseResourceType(wireResourceType), providerBundle));
+                        wiredProviders.add(new TypeProvider(ResourceTypeParser.parseResourceType(wireResourceTypeString), providerBundle));
                         properties.put(ServletResolverConstants.SLING_SERVLET_RESOURCE_SUPER_TYPE, wireResourceTypeString);
                     }
                     populateWiredProviders(wiredProviders);
@@ -209,7 +210,7 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
         Set<String> initialResourceTypes = new HashSet<>(initialProviders.size());
         Set<Bundle> bundles = new HashSet<>(initialProviders.size());
         for (TypeProvider provider : initialProviders) {
-            initialResourceTypes.add(provider.getType());
+            initialResourceTypes.add(provider.getResourceType().toString());
             bundles.add(provider.getBundle());
         }
         for (Bundle bundle : bundles) {
@@ -222,7 +223,8 @@ public class BundledScriptTracker implements BundleTrackerCustomizer<List<Servic
                         Version version = (Version) bundleWire.getCapability().getAttributes().get(BundledScriptTracker
                                 .AT_VERSION);
                         if (!initialResourceTypes.contains(resourceType)) {
-                            initialProviders.add(new TypeProvider(resourceType + (version == null ? "" : "/" + version.toString()),
+                            initialProviders.add(new TypeProvider(
+                                    ResourceTypeParser.parseResourceType(resourceType + (version == null ? "" : "/" + version.toString())),
                                     bundleWire.getProvider().getBundle()));
                         }
                     }
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java
index 122a85c..0dbe226 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/ResourceTypeParser.java
@@ -92,6 +92,11 @@ final class ResourceTypeParser {
         String getVersion() {
             return version;
         }
+
+        @Override
+        public String toString() {
+            return type + (version == null ? "" : "/" + version);
+        }
     }
 
     /**
diff --git a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
index 65d71d6..d1db81d 100644
--- a/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
+++ b/src/main/java/org/apache/sling/scripting/bundle/tracker/internal/TypeProvider.java
@@ -25,17 +25,17 @@ import org.osgi.framework.Bundle;
  */
 public class TypeProvider {
 
-    private String type;
-    private Bundle bundle;
+    private final ResourceTypeParser.ResourceType resourceType;
+    private final Bundle bundle;
 
     /**
      * Builds a {@code TypeProvider}.
      *
-     * @param type   the resource type
+     * @param resourceType   the resource type
      * @param bundle the bundle that provides the resource type
      */
-    TypeProvider(String type, Bundle bundle) {
-        this.type = type;
+    TypeProvider(ResourceTypeParser.ResourceType resourceType, Bundle bundle) {
+        this.resourceType = resourceType;
         this.bundle = bundle;
     }
 
@@ -44,8 +44,8 @@ public class TypeProvider {
      *
      * @return the resource type
      */
-    String getType() {
-        return type;
+    ResourceTypeParser.ResourceType getResourceType() {
+        return resourceType;
     }
 
     /**
@@ -59,7 +59,7 @@ public class TypeProvider {
 
     @Override
     public int hashCode() {
-        return type.hashCode() ^ bundle.hashCode();
+        return resourceType.hashCode() ^ bundle.hashCode();
     }
 
     @Override
@@ -68,6 +68,6 @@ public class TypeProvider {
             return false;
         }
         TypeProvider other = (TypeProvider) obj;
-        return other.bundle.equals(bundle) && other.type.equals(type);
+        return other.bundle.equals(bundle) && other.resourceType.equals(resourceType);
     }
 }