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-sightly.git
commit fde8c6e0155b2d966051cc6170ea3ad79dad3362 Author: Radu Cotescu <[email protected]> AuthorDate: Thu Apr 9 21:58:46 2020 +0200 SLING-9328 - Allow loading template libraries from bundles --- pom.xml | 2 +- .../sightly/impl/engine/SightlyScriptEngine.java | 12 +- .../impl/engine/SightlyScriptEngineFactory.java | 6 +- .../impl/engine/bundled/BundledUnitManager.java | 264 +++++++++++++++++++++ .../impl/engine/extension/use/JavaUseProvider.java | 12 +- .../engine/extension/use/RenderUnitProvider.java | 10 + .../engine/precompiled/PrecompiledUnitManager.java | 112 --------- 7 files changed, 290 insertions(+), 128 deletions(-) diff --git a/pom.xml b/pom.xml index 942cb77..e759385 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,7 @@ The versioning scheme defined here corresponds to SLING-7406 (<module_version>-<htl_specification_version>). Take care when releasing to only increase the first part, unless the module provides support for a newer version of the HTL specification. --> - <version>1.3.3-1.4.0-SNAPSHOT</version> + <version>1.4.0-1.4.0-SNAPSHOT</version> <name>Apache Sling Scripting HTL Engine</name> <description> 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 b07d65a..ef0baf1 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 @@ -28,7 +28,7 @@ import javax.script.ScriptContext; import javax.script.ScriptException; import org.apache.sling.scripting.api.AbstractSlingScriptEngine; -import org.apache.sling.scripting.sightly.impl.engine.precompiled.PrecompiledUnitManager; +import org.apache.sling.scripting.sightly.impl.engine.bundled.BundledUnitManager; import org.apache.sling.scripting.sightly.impl.engine.compiled.SlingHTLMasterCompiler; import org.apache.sling.scripting.sightly.render.RenderUnit; import org.slf4j.Logger; @@ -42,15 +42,15 @@ public class SightlyScriptEngine extends AbstractSlingScriptEngine implements Co private static final Logger LOGGER = LoggerFactory.getLogger(SightlyScriptEngine.class); private SlingHTLMasterCompiler slingHTLMasterCompiler; - private PrecompiledUnitManager precompiledUnitManager; + private BundledUnitManager bundledUnitManager; private ExtensionRegistryService extensionRegistryService; SightlyScriptEngine(SightlyScriptEngineFactory factory, ExtensionRegistryService extensionRegistryService, - SlingHTLMasterCompiler slingHTLMasterCompiler, PrecompiledUnitManager precompiledUnitManager) { + SlingHTLMasterCompiler slingHTLMasterCompiler, BundledUnitManager bundledUnitManager) { super(factory); this.extensionRegistryService = extensionRegistryService; this.slingHTLMasterCompiler = slingHTLMasterCompiler; - this.precompiledUnitManager = precompiledUnitManager; + this.bundledUnitManager = bundledUnitManager; } @Override @@ -71,10 +71,10 @@ public class SightlyScriptEngine extends AbstractSlingScriptEngine implements Co checkArguments(reader, scriptContext); try { SightlyCompiledScript compiledScript = null; - if (precompiledUnitManager != null) { + if (bundledUnitManager != null) { Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE); if (bindings != null) { - RenderUnit renderUnit = precompiledUnitManager.getRenderUnit(bindings); + RenderUnit renderUnit = bundledUnitManager.getRenderUnit(bindings); if (renderUnit != null) { compiledScript = new SightlyCompiledScript(this, renderUnit); } 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 e6b1afd..86ba1dc 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 @@ -22,8 +22,8 @@ import javax.script.ScriptEngine; import javax.script.ScriptEngineFactory; import org.apache.sling.scripting.api.AbstractScriptEngineFactory; +import org.apache.sling.scripting.sightly.impl.engine.bundled.BundledUnitManager; 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; @@ -49,7 +49,7 @@ public class SightlyScriptEngineFactory extends AbstractScriptEngineFactory { private SlingHTLMasterCompiler slingHTLMasterCompiler; @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY) - private PrecompiledUnitManager precompiledUnitManager; + private BundledUnitManager bundledUnitManager; @Reference private ExtensionRegistryService extensionRegistryService; @@ -77,6 +77,6 @@ public class SightlyScriptEngineFactory extends AbstractScriptEngineFactory { @Override public ScriptEngine getScriptEngine() { - return new SightlyScriptEngine(this, extensionRegistryService, slingHTLMasterCompiler, precompiledUnitManager); + return new SightlyScriptEngine(this, extensionRegistryService, slingHTLMasterCompiler, bundledUnitManager); } } diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/bundled/BundledUnitManager.java b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/bundled/BundledUnitManager.java new file mode 100644 index 0000000..75732de --- /dev/null +++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/bundled/BundledUnitManager.java @@ -0,0 +1,264 @@ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ~ 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.bundled; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.URL; +import java.nio.charset.StandardCharsets; + +import javax.script.Bindings; +import javax.script.CompiledScript; +import javax.script.ScriptEngineManager; +import javax.script.ScriptException; + +import org.apache.sling.api.resource.Resource; +import org.apache.sling.commons.compiler.source.JavaEscapeHelper; +import org.apache.sling.scripting.api.CachedScript; +import org.apache.sling.scripting.api.ScriptCache; +import org.apache.sling.scripting.bundle.tracker.BundledRenderUnit; +import org.apache.sling.scripting.bundle.tracker.ResourceType; +import org.apache.sling.scripting.bundle.tracker.TypeProvider; +import org.apache.sling.scripting.core.ScriptNameAwareReader; +import org.apache.sling.scripting.sightly.impl.engine.SightlyCompiledScript; +import org.apache.sling.scripting.sightly.impl.engine.SightlyScriptEngine; +import org.apache.sling.scripting.sightly.impl.utils.BindingsUtils; +import org.apache.sling.scripting.sightly.render.RenderUnit; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.wiring.BundleWiring; +import org.osgi.service.component.annotations.Activate; +import org.osgi.service.component.annotations.Component; +import org.osgi.service.component.annotations.Deactivate; +import org.osgi.service.component.annotations.Reference; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * The {@code BundledUnitManager} is an optional service, which is made available only if the {@link + * org.apache.sling.scripting.bundle.tracker} APIs are available. This service allows various components to work with {@link + * org.apache.sling.scripting.bundle.tracker.BundledRenderUnit} instance and perform dependency resolution based on their availability in + * the {@link Bindings} maps passed to the HTL Script Engine. + */ +@Component( + service = {} + /* + * this component will register itself as a service only if the org.apache.sling.scripting.bundle.tracker API is present + */ + ) +public class BundledUnitManager { + + private static final Logger LOGGER = LoggerFactory.getLogger(BundledUnitManager.class); + + private final ServiceRegistration<?> serviceRegistration; + + @Reference + private ScriptEngineManager scriptEngineManager; + + @Reference + private ScriptCache scriptCache; + + @Activate + public BundledUnitManager(BundleContext bundleContext) { + serviceRegistration = register(bundleContext); + } + + @Deactivate + public void deactivate() { + if (serviceRegistration != null) { + serviceRegistration.unregister(); + } + } + + + /** + * Given a {@link Bindings} map, this method will check if the {@code bindings} contain a value for the {@link + * BundledRenderUnit#VARIABLE} property and return the object provided by {@link BundledRenderUnit#getUnit()} if this is an instance of + * a {@link RenderUnit}. + * + * @param bindings the bindings passed initially to the HTL Script Engine + * @return a {@link RenderUnit} if one is found, {@code null} otherwise + */ + @Nullable + public RenderUnit getRenderUnit(@NotNull Bindings bindings) { + BundledRenderUnit bundledRenderUnit = getBundledRenderUnit(bindings); + if (bundledRenderUnit != null) { + Object renderUnit = bundledRenderUnit.getUnit(); + if (renderUnit instanceof RenderUnit) { + return (RenderUnit) renderUnit; + } + } + return null; + } + + /** + * <p> + * Given a {@link Bindings} map, this method will check if the {@code bindings} contain a value for the {@link + * BundledRenderUnit#VARIABLE} property and if the object provided by {@link BundledRenderUnit#getUnit()} is an instance of a {@link + * RenderUnit}. If so, this service will try to locate another {@link RenderUnit} based on the passed {@code identifier} and the + * coordinates of the {@link RenderUnit} found in the {@code bindings} map. + * </p> + * <p> + * This method is suited for finding template libraries (collections of templates provided by the same {@link RenderUnit}). + * </p> + * + * @param bindings the bindings passed initially to the HTL Script Engine + * @param identifier the identifier of the {@link RenderUnit} that has to be retrieved and returned + * @return a {@link RenderUnit} if one is found, {@code null} otherwise + */ + @Nullable + public RenderUnit getRenderUnit(@NotNull Bindings bindings, @NotNull String identifier) { + BundledRenderUnit bundledRenderUnit = getBundledRenderUnit(bindings); + Resource currentResource = BindingsUtils.getResource(bindings); + if (currentResource != null && bundledRenderUnit != null) { + boolean absolute = identifier.charAt(0) == '/'; + for (TypeProvider provider : bundledRenderUnit.getTypeProviders()) { + for (ResourceType type : provider.getBundledRenderUnitCapability().getResourceTypes()) { + StringBuilder renderUnitIdentifier = new StringBuilder(identifier); + if (!absolute) { + renderUnitIdentifier = renderUnitIdentifier.insert(0, type.toString() + "/"); + } + if (provider.isPrecompiled()) { + String classResourcePath = renderUnitIdentifier.toString(); + if (classResourcePath.startsWith("/")) { + classResourcePath = classResourcePath.substring(1); + } + String className = JavaEscapeHelper.makeJavaPackage(classResourcePath); + try { + Class<?> clazz = provider.getBundle().loadClass(className); + if (clazz.getSuperclass() == RenderUnit.class) { + return (RenderUnit) clazz.getDeclaredConstructor().newInstance(); + } + } catch (RuntimeException e) { + throw e; + } catch (Exception ignored) { + // do nothing here + } + } else { + String scriptResourcePath = renderUnitIdentifier.toString(); + if (scriptResourcePath.startsWith("/")) { + scriptResourcePath = scriptResourcePath.substring(1); + } + URL bundledScriptURL = provider.getBundle().getEntry("javax.script" + "/" + scriptResourcePath); + if (bundledScriptURL != null) { + try { + SightlyScriptEngine sightlyScriptEngine = (SightlyScriptEngine) scriptEngineManager.getEngineByName( + "htl"); + if (sightlyScriptEngine != null) { + CachedScript cachedScript = scriptCache.getScript(bundledScriptURL.toExternalForm()); + if (cachedScript != null) { + return ((SightlyCompiledScript) cachedScript.getCompiledScript()).getRenderUnit(); + } else { + final String finalRenderUnitIdentifier = renderUnitIdentifier.toString(); + try (ScriptNameAwareReader reader = + new ScriptNameAwareReader(new InputStreamReader(bundledScriptURL.openStream(), + StandardCharsets.UTF_8), + finalRenderUnitIdentifier)) { + SightlyCompiledScript compiledScript = + (SightlyCompiledScript) sightlyScriptEngine.compile(reader); + scriptCache.putScript(new CachedScript() { + @Override + public String getScriptPath() { + return bundledScriptURL.toExternalForm(); + } + + @Override + public CompiledScript getCompiledScript() { + return compiledScript; + } + }); + return compiledScript.getRenderUnit(); + } + } + } + } catch (IOException | ScriptException ignored) { + + } + } + } + } + } + } + return null; + } + + /** + * <p> + * Given a {@link Bindings} map, this method will check if the {@code bindings} contain a value for the {@link + * BundledRenderUnit#VARIABLE} property and if the object provided by {@link BundledRenderUnit#getUnit()} is an instance of a {@link + * RenderUnit}. If so, this service will return the {@link ClassLoader} of the {@link org.osgi.framework.Bundle} providing the {@link + * BundledRenderUnit}.</p> + * + * @param bindings the bindings passed initially to the HTL Script Engine + * @return the {@link BundledRenderUnit}'s classloader if one is found, {@code null} otherwise + */ + @Nullable + public ClassLoader getBundledRenderUnitClassloader(Bindings bindings) { + Object bru = bindings.get(BundledRenderUnit.VARIABLE); + if (bru instanceof BundledRenderUnit) { + BundledRenderUnit bundledRenderUnit = (BundledRenderUnit) bru; + return bundledRenderUnit.getBundle().adapt(BundleWiring.class).getClassLoader(); + } + return null; + } + + /** + * <p> + * Given a {@link Bindings} map, this method will check if the {@code bindings} contain a value for the {@link + * BundledRenderUnit#VARIABLE} property and if the object provided by {@link BundledRenderUnit#getUnit()} is an instance of a {@link + * RenderUnit}. If so, this service will try to get a reference to a service of type {@code clazz} and return the service object. The + * service will be retrieved using the bundle context of the {@link BundledRenderUnit} found in the {@code bindings} map.</p> + * + * @param bindings the bindings passed initially to the HTL Script Engine + * @param clazz the class identifying the type of the service + * @param <T> the service type + * @return a service object, if one is found, {@code null} otherwise + */ + @Nullable + public <T> T getServiceForBundledRenderUnit(Bindings bindings, Class<T> clazz) { + Object bru = bindings.get(BundledRenderUnit.VARIABLE); + if (bru instanceof BundledRenderUnit) { + BundledRenderUnit bundledRenderUnit = (BundledRenderUnit) bru; + return bundledRenderUnit.getService(clazz.getName()); + } + return null; + } + + private ServiceRegistration<?> register(BundleContext bundleContext) { + try { + BundledUnitManager.class.getClassLoader().loadClass("org.apache.sling.scripting.bundle.tracker.BundledRenderUnit"); + return bundleContext.registerService(BundledUnitManager.class, this, null); + } catch (ClassNotFoundException e) { + LOGGER.info("No support for bundled RenderUnits."); + } + return null; + } + + @Nullable + private BundledRenderUnit getBundledRenderUnit(Bindings bindings) { + Object bru = bindings.get(BundledRenderUnit.VARIABLE); + if (bru instanceof BundledRenderUnit) { + return (BundledRenderUnit) bru; + } + return null; + } + +} 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 d2ceed3..c792921 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 @@ -30,8 +30,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.sightly.impl.engine.bundled.BundledUnitManager; 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; @@ -77,7 +77,7 @@ public class JavaUseProvider implements UseProvider { private SlingHTLMasterCompiler slingHTLMasterCompiler; @Reference(cardinality = ReferenceCardinality.OPTIONAL, policyOption = ReferencePolicyOption.GREEDY) - private PrecompiledUnitManager precompiledUnitManager; + private BundledUnitManager bundledUnitManager; @Override public ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments) { @@ -91,20 +91,20 @@ public class JavaUseProvider implements UseProvider { try { Exception failure = null; - if (precompiledUnitManager != null) { - ClassLoader unitClassLoader = precompiledUnitManager.getBundledRenderUnitClassloader(globalBindings); + if (bundledUnitManager != null) { + ClassLoader unitClassLoader = bundledUnitManager.getBundledRenderUnitClassloader(globalBindings); if (unitClassLoader != null) { try { String className = identifier; if (className.indexOf('.') < 0) { // the class name is not fully qualified; need to prepend the package name of the current rendering unit - RenderUnit renderUnit = precompiledUnitManager.getRenderUnit(globalBindings); + RenderUnit renderUnit = bundledUnitManager.getRenderUnit(globalBindings); if (renderUnit != null) { className = renderUnit.getClass().getPackage().getName() + "." + className; } } Class<?> clazz = unitClassLoader.loadClass(className); - return loadObject(clazz, cls -> precompiledUnitManager.getServiceForBundledRenderUnit(globalBindings, clazz), + return loadObject(clazz, cls -> bundledUnitManager.getServiceForBundledRenderUnit(globalBindings, clazz), globalBindings, arguments); } catch (Exception e) { diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/RenderUnitProvider.java b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/RenderUnitProvider.java index df29230..4e51995 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/RenderUnitProvider.java +++ b/src/main/java/org/apache/sling/scripting/sightly/impl/engine/extension/use/RenderUnitProvider.java @@ -39,6 +39,7 @@ import org.apache.sling.scripting.sightly.engine.ResourceResolution; import org.apache.sling.scripting.sightly.impl.engine.SightlyCompiledScript; import org.apache.sling.scripting.sightly.impl.engine.SightlyScriptEngine; import org.apache.sling.scripting.sightly.impl.engine.SightlyScriptEngineFactory; +import org.apache.sling.scripting.sightly.impl.engine.bundled.BundledUnitManager; import org.apache.sling.scripting.sightly.impl.utils.BindingsUtils; import org.apache.sling.scripting.sightly.impl.utils.ScriptUtils; import org.apache.sling.scripting.sightly.render.RenderContext; @@ -76,6 +77,9 @@ public class RenderUnitProvider implements UseProvider { private ScriptCache scriptCache; @Reference + private BundledUnitManager bundledUnitManager; + + @Reference private ScriptEngineManager scriptEngineManager; @Reference @@ -85,6 +89,12 @@ public class RenderUnitProvider implements UseProvider { public ProviderOutcome provide(String identifier, RenderContext renderContext, Bindings arguments) { if (identifier.endsWith("." + SightlyScriptEngineFactory.EXTENSION)) { Bindings globalBindings = renderContext.getBindings(); + if (bundledUnitManager != null) { + RenderUnit renderUnit = bundledUnitManager.getRenderUnit(globalBindings, identifier); + if (renderUnit != null) { + return ProviderOutcome.success(renderUnit); + } + } SlingScriptHelper sling = BindingsUtils.getHelper(globalBindings); SlingHttpServletRequest request = BindingsUtils.getRequest(globalBindings); final Resource renderUnitResource = ScriptUtils.resolveScript(scriptingResourceResolverProvider 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 deleted file mode 100644 index 94de4c9..0000000 --- a/src/main/java/org/apache/sling/scripting/sightly/impl/engine/precompiled/PrecompiledUnitManager.java +++ /dev/null @@ -1,112 +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.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.jetbrains.annotations.Nullable; -import org.osgi.framework.BundleContext; -import org.osgi.framework.ServiceRegistration; -import org.osgi.framework.wiring.BundleWiring; -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( - service = {} - /* - * this component will register itself as a service only if the org.apache.sling.scripting.bundle.tracker API is present - */ -) -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 extracting 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 bindings the global bindings of the script execution context - * @return an instance of the compiled script, if a precompiled {@link RenderUnit} was present in the {@link ScriptContext}, {@code - * null} otherwise - */ - @Nullable - public RenderUnit getRenderUnit(Bindings bindings) { - Object bundledRenderUnit = bindings.get(BundledRenderUnit.VARIABLE); - if (bundledRenderUnit instanceof BundledRenderUnit) { - Object renderUnit = ((BundledRenderUnit) bundledRenderUnit).getUnit(); - if (renderUnit instanceof RenderUnit) { - return (RenderUnit) renderUnit; - } - } - return null; - } - - @Nullable - public ClassLoader getBundledRenderUnitClassloader(Bindings bindings) { - Object bru = bindings.get(BundledRenderUnit.VARIABLE); - if (bru instanceof BundledRenderUnit) { - BundledRenderUnit bundledRenderUnit = (BundledRenderUnit) bru; - return bundledRenderUnit.getBundle().adapt(BundleWiring.class).getClassLoader(); - } - return null; - } - - @Nullable - public <T> T getServiceForBundledRenderUnit(Bindings bindings, Class<?> clazz) { - Object bru = bindings.get(BundledRenderUnit.VARIABLE); - if (bru instanceof BundledRenderUnit) { - BundledRenderUnit bundledRenderUnit = (BundledRenderUnit) bru; - return bundledRenderUnit.getService(clazz.getName()); - } - 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 (ClassNotFoundException e) { - LOGGER.info("No support for precompiled scripts."); - } - return null; - } -}
