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 2019/08/26 15:34:09 UTC

[sling-org-apache-sling-scripting-sightly] branch experimental-scripting-resolver updated: SLING-8660 - Add optional support for precompiled scripts in the HTL engine

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

radu pushed a commit to branch experimental-scripting-resolver
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly.git


The following commit(s) were added to refs/heads/experimental-scripting-resolver by this push:
     new b535684  SLING-8660 - Add optional support for precompiled scripts in the HTL engine
b535684 is described below

commit b535684768c83a4322d96020a62e93c9fa36c39e
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Mon Aug 26 17:30:25 2019 +0200

    SLING-8660 - Add optional support for precompiled scripts in the HTL engine
    
    * if the org.apache.sling.scripting.bundle.tracker API is present, the engine tries
    to execute precompiled scripts present in the ScriptContext
---
 bnd.bnd                                            | 14 +++-
 .../sightly/impl/engine/SightlyScriptEngine.java   | 39 +++------
 .../impl/engine/SightlyScriptEngineFactory.java    |  6 +-
 .../impl/engine/extension/use/JavaUseProvider.java | 86 ++++++++++----------
 .../engine/precompiled/PrecompiledUnitManager.java | 95 ++++++++++++++++++++++
 .../impl/engine/runtime/RenderContextImpl.java     |  5 --
 6 files changed, 163 insertions(+), 82 deletions(-)

diff --git a/bnd.bnd b/bnd.bnd
index 8482428..7e396f2 100644
--- a/bnd.bnd
+++ b/bnd.bnd
@@ -1,3 +1,13 @@
-Provide-Capability: io.sightly;version:Version="1.0", io.sightly; version:Version="1.1", io.sightly;version:Version="1.2", io.sightly;version:Version="1.3", io.sightly;version:Version="1.3.1", io.sightly;version:Version="1.4"
+Provide-Capability: io.sightly;version:Version="1.0", \\
+                    io.sightly;version:Version="1.1", \\
+                    io.sightly;version:Version="1.2", \\
+                    io.sightly;version:Version="1.3", \\
+                    io.sightly;version:Version="1.3.1", \\
+                    io.sightly;version:Version="1.4"
 Require-Capability: io.sightly.runtime; filter:="(&(version<=1.0)(!(version>=2.0)))"
-Import-Package:     org.apache.sling.scripting.sightly.compiler.*;resolution:=optional, org.apache.sling.scripting.sightly.java.compiler.*;resolution:=optional, org.apache.sling.commons.compiler.*;resolution:=optional, org.apache.sling.commons.classloader.*;resolution:=optional,*
+Import-Package:     org.apache.sling.scripting.sightly.compiler.*;resolution:=optional, \\
+                    org.apache.sling.scripting.sightly.java.compiler.*;resolution:=optional, \\
+                    org.apache.sling.commons.compiler.*;resolution:=optional, \\
+                    org.apache.sling.commons.classloader.*;resolution:=optional, \\
+                    org.apache.sling.scripting.bundle.tracker.*;resolution:=optional, \\
+                    *
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngine.java b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngine.java
index b6b6987..5a15583 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngine.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngine.java
@@ -21,29 +21,14 @@ package org.apache.sling.scripting.sightly.impl.engine;
 import java.io.Reader;
 import java.io.StringReader;
 
-import javax.script.Bindings;
 import javax.script.Compilable;
 import javax.script.CompiledScript;
 import javax.script.ScriptContext;
 import javax.script.ScriptException;
 
 import org.apache.sling.scripting.api.AbstractSlingScriptEngine;
-import org.apache.sling.scripting.api.ScriptNameAware;
-import org.apache.sling.scripting.api.resource.ScriptingResourceResolverProvider;
-import org.apache.sling.scripting.bundle.tracker.BundledRenderUnit;
-import org.apache.sling.scripting.sightly.SightlyException;
-import org.apache.sling.scripting.sightly.compiler.CompilationResult;
-import org.apache.sling.scripting.sightly.compiler.CompilationUnit;
-import org.apache.sling.scripting.sightly.compiler.CompilerMessage;
-import org.apache.sling.scripting.sightly.compiler.SightlyCompiler;
-import org.apache.sling.scripting.sightly.impl.engine.compiled.SourceIdentifier;
-import org.apache.sling.scripting.sightly.impl.utils.BindingsUtils;
-import org.apache.sling.scripting.sightly.java.compiler.GlobalShadowCheckBackendCompiler;
-import org.apache.sling.scripting.sightly.java.compiler.JavaClassBackendCompiler;
-import org.apache.sling.scripting.sightly.java.compiler.JavaEscapeUtils;
-import org.apache.sling.scripting.sightly.java.compiler.JavaImportsAnalyzer;
+import org.apache.sling.scripting.sightly.impl.engine.precompiled.PrecompiledUnitManager;
 import org.apache.sling.scripting.sightly.impl.engine.compiled.SlingHTLMasterCompiler;
-import org.apache.sling.scripting.sightly.render.RenderUnit;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -55,12 +40,15 @@ public class SightlyScriptEngine extends AbstractSlingScriptEngine implements Co
     private static final Logger LOGGER = LoggerFactory.getLogger(SightlyScriptEngine.class);
 
     private SlingHTLMasterCompiler slingHTLMasterCompiler;
+    private PrecompiledUnitManager precompiledUnitManager;
     private ExtensionRegistryService extensionRegistryService;
 
-    SightlyScriptEngine(SightlyScriptEngineFactory factory, ExtensionRegistryService extensionRegistryService, SlingHTLMasterCompiler slingHTLMasterCompiler) {
+    SightlyScriptEngine(SightlyScriptEngineFactory factory, ExtensionRegistryService extensionRegistryService,
+                        SlingHTLMasterCompiler slingHTLMasterCompiler, PrecompiledUnitManager precompiledUnitManager) {
         super(factory);
         this.extensionRegistryService = extensionRegistryService;
         this.slingHTLMasterCompiler = slingHTLMasterCompiler;
+        this.precompiledUnitManager = precompiledUnitManager;
     }
 
     @Override
@@ -81,21 +69,14 @@ public class SightlyScriptEngine extends AbstractSlingScriptEngine implements Co
         checkArguments(reader, scriptContext);
         try {
             SightlyCompiledScript compiledScript = null;
-            Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
-            Object bundledRenderUnit = bindings.get(BundledRenderUnit.VARIABLE);
-            Object renderUnit = null;
-            if (bundledRenderUnit instanceof BundledRenderUnit) {
-                renderUnit = ((BundledRenderUnit) bundledRenderUnit).getUnit();
-                if (renderUnit instanceof RenderUnit) {
-                    compiledScript = new SightlyCompiledScript(this, (RenderUnit) renderUnit);
-                    return compiledScript.eval(scriptContext);
-                }
+            if (precompiledUnitManager != null) {
+                compiledScript = precompiledUnitManager.evaluate(this, scriptContext);
             }
             if (slingHTLMasterCompiler != null) {
                 compiledScript = slingHTLMasterCompiler.compileHTLScript(this, reader, scriptContext);
-                if (compiledScript != null) {
-                    return compiledScript.eval(scriptContext);
-                }
+            }
+            if (compiledScript != null) {
+                return compiledScript.eval(scriptContext);
             }
         } catch (Exception e) {
             throw new ScriptException(e);
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java
index 257482d..e6b1afd 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/SightlyScriptEngineFactory.java
@@ -23,6 +23,7 @@ import javax.script.ScriptEngineFactory;
 
 import org.apache.sling.scripting.api.AbstractScriptEngineFactory;
 import org.apache.sling.scripting.sightly.impl.engine.compiled.SlingHTLMasterCompiler;
+import org.apache.sling.scripting.sightly.impl.engine.precompiled.PrecompiledUnitManager;
 import org.osgi.framework.Constants;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
@@ -47,6 +48,9 @@ public class SightlyScriptEngineFactory extends AbstractScriptEngineFactory {
     @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
     private SlingHTLMasterCompiler slingHTLMasterCompiler;
 
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
+    private PrecompiledUnitManager precompiledUnitManager;
+
     @Reference
     private ExtensionRegistryService extensionRegistryService;
 
@@ -73,6 +77,6 @@ public class SightlyScriptEngineFactory extends AbstractScriptEngineFactory {
 
     @Override
     public ScriptEngine getScriptEngine() {
-        return new SightlyScriptEngine(this, extensionRegistryService, slingHTLMasterCompiler);
+        return new SightlyScriptEngine(this, extensionRegistryService, slingHTLMasterCompiler, precompiledUnitManager);
     }
 }
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java
index 5e518ed..6a45676 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/JavaUseProvider.java
@@ -29,8 +29,8 @@ import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.adapter.Adaptable;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.scripting.SlingScriptHelper;
-import org.apache.sling.scripting.bundle.tracker.BundledRenderUnit;
 import org.apache.sling.scripting.sightly.impl.engine.compiled.SlingHTLMasterCompiler;
+import org.apache.sling.scripting.sightly.impl.engine.precompiled.PrecompiledUnitManager;
 import org.apache.sling.scripting.sightly.impl.utils.BindingsUtils;
 import org.apache.sling.scripting.sightly.impl.utils.Patterns;
 import org.apache.sling.scripting.sightly.pojo.Use;
@@ -38,7 +38,6 @@ import org.apache.sling.scripting.sightly.render.RenderContext;
 import org.apache.sling.scripting.sightly.use.ProviderOutcome;
 import org.apache.sling.scripting.sightly.use.UseProvider;
 import org.osgi.framework.Constants;
-import org.osgi.framework.wiring.BundleWiring;
 import org.osgi.service.component.annotations.Component;
 import org.osgi.service.component.annotations.Reference;
 import org.osgi.service.component.annotations.ReferenceCardinality;
@@ -73,6 +72,9 @@ public class JavaUseProvider implements UseProvider {
     @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
     private SlingHTLMasterCompiler slingHTLMasterCompiler;
 
+    @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY)
+    private PrecompiledUnitManager precompiledUnitManager;
+
     @Override
     public ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments) {
         if (!Patterns.JAVA_CLASS_NAME.matcher(identifier).matches()) {
@@ -96,57 +98,51 @@ public class JavaUseProvider implements UseProvider {
                 return ProviderOutcome.success(result);
             } else {
                 LOG.debug("Attempting to load class {} from the classloader cache.", identifier);
-                BundledRenderUnit bundledRenderUnit = null;
-                ClassLoader classLoader = null;
-                Object bru = globalBindings.get(BundledRenderUnit.VARIABLE);
-                if (bru instanceof BundledRenderUnit) {
-                    bundledRenderUnit = (BundledRenderUnit) bru;
-                    classLoader = bundledRenderUnit.getBundle().adapt(BundleWiring.class).getClassLoader();
-                } else {
-                    if (slingHTLMasterCompiler != null) {
-                        classLoader = slingHTLMasterCompiler.getClassLoader();
+                if (precompiledUnitManager != null) {
+                    result = precompiledUnitManager.getBundledRenderUnitDependency(globalBindings, identifier);
+                    if (result != null) {
+                        return ProviderOutcome.success(result);
                     }
                 }
-                // attempt OSGi service load
-                if (classLoader != null) {
-                    Class<?> cls = classLoader.loadClass(identifier);
+                if (slingHTLMasterCompiler != null) {
+                    ClassLoader classLoader = slingHTLMasterCompiler.getClassLoader();
                     // attempt OSGi service load
-                    if (bundledRenderUnit != null) {
-                        result = bundledRenderUnit.getService(identifier);
-                    } else {
+                    if (classLoader != null) {
+                        Class<?> cls = classLoader.loadClass(identifier);
+                        // attempt OSGi service load
                         result = sling.getService(cls);
-                    }
-                    if (result != null) {
-                        return ProviderOutcome.success(result);
-                    }
-                    Object adaptableCandidate = arguments.get(ADAPTABLE);
-                    if (adaptableCandidate instanceof Adaptable) {
-                        Adaptable adaptable = (Adaptable) adaptableCandidate;
-                        result = adaptable.adaptTo(cls);
                         if (result != null) {
                             return ProviderOutcome.success(result);
                         }
-                    }
-                    result = request.adaptTo(cls);
-                    if (result == null) {
-                        Resource resource = BindingsUtils.getResource(globalBindings);
-                        result = resource.adaptTo(cls);
-                    }
-                    if (result != null) {
-                        return ProviderOutcome.success(result);
-                    } else if (cls.isInterface() || Modifier.isAbstract(cls.getModifiers())) {
-                        LOG.debug("Wont attempt to instantiate an interface or abstract class {}", cls.getName());
-                        return ProviderOutcome.failure();
-                    } else {
-                        /*
-                         * the object was cached by the class loader but it's not adaptable from {@link Resource} or {@link
-                         * SlingHttpServletRequest}; attempt to load it like a regular POJO that optionally could implement {@link Use}
-                         */
-                        result = cls.newInstance();
-                        if (result instanceof Use) {
-                            ((Use) result).init(BindingsUtils.merge(globalBindings, arguments));
+                        Object adaptableCandidate = arguments.get(ADAPTABLE);
+                        if (adaptableCandidate instanceof Adaptable) {
+                            Adaptable adaptable = (Adaptable) adaptableCandidate;
+                            result = adaptable.adaptTo(cls);
+                            if (result != null) {
+                                return ProviderOutcome.success(result);
+                            }
+                        }
+                        result = request.adaptTo(cls);
+                        if (result == null) {
+                            Resource resource = BindingsUtils.getResource(globalBindings);
+                            result = resource.adaptTo(cls);
+                        }
+                        if (result != null) {
+                            return ProviderOutcome.success(result);
+                        } else if (cls.isInterface() || Modifier.isAbstract(cls.getModifiers())) {
+                            LOG.debug("Wont attempt to instantiate an interface or abstract class {}", cls.getName());
+                            return ProviderOutcome.failure();
+                        } else {
+                            /*
+                             * the object was cached by the class loader but it's not adaptable from {@link Resource} or {@link
+                             * SlingHttpServletRequest}; attempt to load it like a regular POJO that optionally could implement {@link Use}
+                             */
+                            result = cls.newInstance();
+                            if (result instanceof Use) {
+                                ((Use) result).init(BindingsUtils.merge(globalBindings, arguments));
+                            }
+                            return ProviderOutcome.notNullOrFailure(result);
                         }
-                        return ProviderOutcome.notNullOrFailure(result);
                     }
                 }
                 return ProviderOutcome.failure();
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/precompiled/PrecompiledUnitManager.java b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/precompiled/PrecompiledUnitManager.java
new file mode 100644
index 0000000..fcdfc36
--- /dev/null
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/precompiled/PrecompiledUnitManager.java
@@ -0,0 +1,95 @@
+/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ 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.sightly.impl.engine.precompiled;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+
+import org.apache.sling.scripting.bundle.tracker.BundledRenderUnit;
+import org.apache.sling.scripting.sightly.impl.engine.SightlyCompiledScript;
+import org.apache.sling.scripting.sightly.impl.engine.SightlyScriptEngine;
+import org.apache.sling.scripting.sightly.render.RenderUnit;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.annotations.Activate;
+import org.osgi.service.component.annotations.Component;
+import org.osgi.service.component.annotations.Deactivate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(immediate = true)
+public class PrecompiledUnitManager {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(PrecompiledUnitManager.class);
+
+    private final ServiceRegistration<?> serviceRegistration;
+
+    @Activate
+    public PrecompiledUnitManager(BundleContext bundleContext) {
+        serviceRegistration = register(bundleContext);
+    }
+
+    @Deactivate
+    public void deactivate() {
+        if (serviceRegistration != null) {
+            serviceRegistration.unregister();
+        }
+    }
+
+
+    /**
+     * Provides support for evaluating precompiled HTL scripts passed through the {@code scriptContext}. This feature works only when the
+     * {@link org.apache.sling.scripting.bundle.tracker.BundledRenderUnit} API is deployed to the platform as well.
+     *
+     * @param sightlyScriptEngine the HTL script engine providing access to the HTL runtime
+     * @param scriptContext       the script context
+     * @return an instance of the compiled script, if a precompiled {@link RenderUnit} was present in the {@link ScriptContext}, {@code
+     * null} otherwise
+     */
+    public SightlyCompiledScript evaluate(SightlyScriptEngine sightlyScriptEngine, ScriptContext scriptContext) {
+        Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
+        Object bundledRenderUnit = bindings.get(BundledRenderUnit.VARIABLE);
+        if (bundledRenderUnit instanceof BundledRenderUnit) {
+            Object renderUnit = ((BundledRenderUnit) bundledRenderUnit).getUnit();
+            if (renderUnit instanceof RenderUnit) {
+                return new SightlyCompiledScript(sightlyScriptEngine, (RenderUnit) renderUnit);
+            }
+        }
+        return null;
+    }
+
+    public Object getBundledRenderUnitDependency(Bindings bindings, String identifier) {
+        Object bru = bindings.get(BundledRenderUnit.VARIABLE);
+        if (bru instanceof BundledRenderUnit) {
+            BundledRenderUnit bundledRenderUnit = (BundledRenderUnit) bru;
+            return bundledRenderUnit.getService(identifier);
+        }
+        return null;
+    }
+
+    private ServiceRegistration<?> register(BundleContext bundleContext) {
+        try {
+            PrecompiledUnitManager.class.getClassLoader().loadClass("org.apache.sling.scripting.bundle.tracker.BundledRenderUnit");
+            return bundleContext.registerService(PrecompiledUnitManager.class, this, null);
+        } catch (Throwable e) {
+            LOGGER.info("No support for precompiled scripts.");
+        }
+        return null;
+    }
+}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/runtime/RenderContextImpl.java b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/runtime/RenderContextImpl.java
index 77b804c..c26ac77 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/runtime/RenderContextImpl.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/runtime/RenderContextImpl.java
@@ -46,11 +46,6 @@ public class RenderContextImpl implements RenderContext {
     public RenderContextImpl(ExtensionRegistryService extensionRegistryService, ScriptContext scriptContext) {
         this.extensionRegistryService = extensionRegistryService;
         bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
-        Bundle scriptProvidingBundle = (Bundle) scriptContext.getAttribute("org.apache.sling.scripting.bundle.tracker.provider.bundle",
-                SlingScriptConstants.SLING_SCOPE);
-        if (scriptProvidingBundle != null) {
-            bindings.put("org.apache.sling.scripting.sightly.render_unit.loader", scriptProvidingBundle.adapt(BundleWiring.class).getClassLoader());
-        }
     }
 
     @Override