You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by kw...@apache.org on 2017/02/28 08:26:34 UTC
svn commit: r1784700 - in /sling/trunk/bundles/scripting/core: ./
src/main/java/org/apache/sling/scripting/core/impl/
src/main/resources/scriptingvariables/
src/main/resources/scriptingvariables/ui/
Author: kwin
Date: Tue Feb 28 08:26:34 2017
New Revision: 1784700
URL: http://svn.apache.org/viewvc?rev=1784700&view=rev
Log:
SLING-3543 provide dedicated web console for exposing all scripting variables
This closes #135
Added:
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java (with props)
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java (with props)
sling/trunk/bundles/scripting/core/src/main/resources/scriptingvariables/
sling/trunk/bundles/scripting/core/src/main/resources/scriptingvariables/ui/
sling/trunk/bundles/scripting/core/src/main/resources/scriptingvariables/ui/scriptingvariables.js
Modified:
sling/trunk/bundles/scripting/core/pom.xml
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java
Modified: sling/trunk/bundles/scripting/core/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/pom.xml?rev=1784700&r1=1784699&r2=1784700&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/core/pom.xml (original)
+++ sling/trunk/bundles/scripting/core/pom.xml Tue Feb 28 08:26:34 2017
@@ -63,6 +63,8 @@
<Embed-Dependency>
org.apache.sling.commons.osgi;inline="org/apache/sling/commons/osgi/PropertiesUtil.*"
</Embed-Dependency>
+ <!-- statically link JSONWriter (http://njbartlett.name/2014/05/26/static-linking.html) -->
+ <Conditional-Package>org.apache.felix.utils.json.*</Conditional-Package>
</instructions>
</configuration>
</plugin>
@@ -151,11 +153,17 @@
<version>3.1.0</version>
<scope>provided</scope>
</dependency>
-
<dependency>
<groupId>org.osgi</groupId>
<artifactId>osgi.core</artifactId>
</dependency>
+ <!-- for serializing to JSON, must be after osgi.core to make Maven use the correct osgi.core version -->
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.utils</artifactId>
+ <version>1.9.0</version>
+ <scope>compile</scope>
+ </dependency>
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.webconsole</artifactId>
Modified: sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java?rev=1784700&r1=1784699&r2=1784700&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java (original)
+++ sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java Tue Feb 28 08:26:34 2017
@@ -629,7 +629,7 @@ class DefaultSlingScript implements Slin
};
}
- private Bindings verifySlingBindings(final SlingBindings slingBindings) throws IOException {
+ Bindings verifySlingBindings(final SlingBindings slingBindings) throws IOException {
final Bindings bindings = new SimpleBindings();
Added: sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java?rev=1784700&view=auto
==============================================================================
--- sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java (added)
+++ sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java Tue Feb 28 08:26:34 2017
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2016 The Apache Software Foundation.
+ *
+ * Licensed 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.IOException;
+import java.io.PrintWriter;
+import java.net.URL;
+
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.felix.webconsole.AbstractWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleConstants;
+
+/**
+ * Web Console Plugin exposing all binding provider values.
+ * @see <a href="http://felix.apache.org/documentation/subprojects/apache-felix-web-console/extending-the-apache-felix-web-console/providing-web-console-plugins.html></a>
+ */
+@Component
+@Service
+@Properties({
+ @Property(name = WebConsoleConstants.PLUGIN_LABEL, value = ScriptingVariablesConsolePlugin.LABEL),
+ @Property(name = WebConsoleConstants.PLUGIN_TITLE, value = ScriptingVariablesConsolePlugin.TITLE),
+ @Property(name = "felix.webconsole.category", value = "Sling")
+})
+public class ScriptingVariablesConsolePlugin extends AbstractWebConsolePlugin {
+
+ protected static final String LABEL = "scriptingvariables";
+ protected static final String TITLE = "Scripting Variables";
+ /**
+ *
+ */
+ private static final long serialVersionUID = 261709110347150295L;
+
+ private static final String JS_RES_PATH = "scriptingvariables/ui/scriptingvariables.js";
+
+ /**
+ * The script engine manager.
+ */
+ @Reference
+ private ScriptEngineManager scriptEngineManager;
+
+ public ScriptingVariablesConsolePlugin() {
+ }
+
+ /**
+ * Automatically called from
+ * <a href="https://github.com/apache/felix/blob/4a60744d0f88f351551e4cb4673eb60b8fbd21d3/webconsole/src/main/java/org/apache/felix/webconsole/AbstractWebConsolePlugin.java#L510">AbstractWebConsolePlugin#spoolResource</a>
+ *
+ * @param path the requested path
+ * @return either a URL from which to spool the resource requested through the given path or {@code null}
+ */
+ public URL getResource(String path) {
+ if (path.endsWith(JS_RES_PATH)) {
+ return this.getClass().getResource("/" + JS_RES_PATH);
+ }
+ return null;
+ }
+
+ @Override
+ public String getLabel() {
+ return LABEL;
+ }
+
+ @Override
+ public String getTitle() {
+ return TITLE;
+ }
+
+ @Override
+ protected void renderContent(HttpServletRequest request, HttpServletResponse response)
+ throws ServletException, IOException {
+ final PrintWriter pw = response.getWriter();
+ pw.append("<script type='text/javascript' src='").append(JS_RES_PATH).append("'></script>");
+ pw.append("<div id='content'>");
+ pw.append("<table class='content' cellpadding='0' cellspacing='0' width='100%'>");
+ pw.append("<tr><th colspan='3' class='content container'>Sling Scripting Variables</th></tr>");
+ pw.append("<tr class='content'><td class='content' colspan='3'>Provide a resource path url and script engine (via extension) and then click on 'Retrieve Variables' to expose all script bindings variables which are available for that resource and script engine.</td></tr>");
+ pw.append("<tr class='content'>");
+ pw.append("<td class='content'>Resource Url (without selectors and extension)</td> ");
+ pw.append("<td class='content' colspan='2'><input type ='text' name='form.path' placeholder='path' required='required' ");
+ pw.append("class='input ui-state-default ui-corner-all inputText' size='50' pattern='^/{1}.*'></td></tr>");
+ pw.append("<tr class='content'>");
+ pw.append("<td class='content'>Script Engine</td> ");
+ pw.append("<td class='content' colspan='2'><select name='form.extension'>");
+ for (ScriptEngineFactory factory : scriptEngineManager.getEngineFactories()) {
+ for (String extension : factory.getExtensions()) {
+ pw.append("<option value='" + extension + "'>"+extension + " (" + factory.getEngineName() +")</option>");
+ }
+ pw.append("<option value=''>all (unfiltered)</option>");
+ }
+ pw.append("</select> ");
+ pw.append("<button type='button' id='submitButton'> Retrieve Variables </button></td></tr></table>");
+ pw.append("<div id='response'></div>");
+ }
+}
Propchange: sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java?rev=1784700&view=auto
==============================================================================
--- sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java (added)
+++ sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java Tue Feb 28 08:26:34 2017
@@ -0,0 +1,162 @@
+/*
+ * 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.IOException;
+import java.util.Collection;
+import java.util.Map;
+
+import javax.script.Bindings;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptEngineManager;
+import javax.servlet.ServletException;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.sling.SlingServlet;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.api.resource.NonExistingResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptConstants;
+import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
+import org.apache.felix.utils.json.JSONWriter;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Return all scripting variables for all registered scripting languages for the default context (=request).
+ * This can only be achieved when a real Sling request and Sling response is available.
+ * Also the context (i.e. the resource on which the request is acting) is important,
+ * because the actual binding variables might differ depending on the context
+ */
+@SlingServlet(
+ resourceTypes = "sling/servlet/default",
+ selectors = "availablebindings",
+ methods = "GET",
+ extensions = "json"
+)
+public class SlingBindingsVariablesListJsonServlet extends SlingSafeMethodsServlet {
+
+ /**
+ *
+ */
+ private static final long serialVersionUID = -6744726829737263875L;
+
+ /**
+ * The script engine manager.
+ */
+ @Reference
+ private ScriptEngineManager scriptEngineManager;
+
+ /**
+ * The BindingsValuesProviderTracker
+ */
+ @Reference
+ private BindingsValuesProvidersByContext bindingsValuesProviderTracker;
+
+ private BundleContext bundleContext;
+
+ private static final String PARAMETER_EXTENSION = "extension";
+
+ @Activate
+ protected void activate(ComponentContext context) {
+ bundleContext = context.getBundleContext();
+ }
+
+ @Override
+ protected void doGet(SlingHttpServletRequest request, SlingHttpServletResponse response)
+ throws ServletException, IOException {
+ response.setContentType("application/json");
+ JSONWriter jsonWriter = new JSONWriter(response.getWriter());
+ jsonWriter.array();
+ // get filter by engine selector
+ String requestedExtension = request.getParameter(PARAMETER_EXTENSION);
+ if (StringUtils.isNotBlank(requestedExtension)) {
+ ScriptEngine selectedScriptEngine = scriptEngineManager.getEngineByExtension(requestedExtension);
+ if (selectedScriptEngine == null) {
+ throw new IllegalArgumentException("Invalid extension requested: "+requestedExtension);
+ } else {
+ writeBindingsToJsonWriter(jsonWriter, selectedScriptEngine.getFactory(), request, response);
+ }
+ } else {
+ for (ScriptEngineFactory engineFactory : scriptEngineManager.getEngineFactories()) {
+ writeBindingsToJsonWriter(jsonWriter, engineFactory, request, response);
+ }
+ }
+ jsonWriter.endArray();
+ }
+
+ private void writeBindingsToJsonWriter(JSONWriter jsonWriter, ScriptEngineFactory engineFactory, SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
+ jsonWriter.object();
+ jsonWriter.key("engine");
+ jsonWriter.value(engineFactory.getEngineName());
+ jsonWriter.key("extensions");
+ jsonWriter.value(engineFactory.getExtensions());
+ Bindings bindings = getBindingsByEngine(engineFactory, request, response);
+ jsonWriter.key("bindings");
+ jsonWriter.array();
+ for (Map.Entry<String, Object> entry : bindings.entrySet()) {
+ jsonWriter.object();
+ jsonWriter.key("name");
+ jsonWriter.value(entry.getKey());
+ jsonWriter.key("class");
+ jsonWriter.value(entry.getValue().getClass().getName());
+ jsonWriter.endObject();
+ }
+ jsonWriter.endArray();
+ jsonWriter.endObject();
+ }
+
+ /**
+ * Gets the {@link Bindings} object for the given {@link ScriptEngineFactory}.
+ * It only considers the default context "request".
+ *
+ * @see <a href="https://issues.apache.org/jira/browse/SLING-3038">binding contexts(SLING-3083)</a>
+ *
+ * @param scriptEngineFactory the factory of the script engine, for which to retrieve the bindings
+ * @param request the current request (necessary to create the bindings)
+ * @param response the current response (necessary to create the bindings)
+ * @return the bindings (list of key/value pairs) as defined by {@link Bindings} for the given script engine.
+ * @throws IOException
+ * @throws JSONException
+ */
+ private Bindings getBindingsByEngine(ScriptEngineFactory scriptEngineFactory, SlingHttpServletRequest request, SlingHttpServletResponse response) throws IOException {
+ String context = SlingScriptAdapterFactory.BINDINGS_CONTEXT; // use default context only
+ final Collection<BindingsValuesProvider> bindingsValuesProviders =
+ bindingsValuesProviderTracker.getBindingsValuesProviders(scriptEngineFactory, context);
+
+ Resource invalidScriptResource = new NonExistingResource(request.getResourceResolver(), "some/invalid/scriptpath");
+ DefaultSlingScript defaultSlingScript = new DefaultSlingScript(bundleContext, invalidScriptResource, scriptEngineFactory.getScriptEngine(), bindingsValuesProviders, null, null);
+
+ // prepare the bindings (similar as in DefaultSlingScript#service)
+ final SlingBindings initalBindings = new SlingBindings();
+ initalBindings.setRequest((SlingHttpServletRequest) request);
+ initalBindings.setResponse((SlingHttpServletResponse) response);
+ final Bindings bindings = defaultSlingScript.verifySlingBindings(initalBindings);
+
+ // only thing being added in {DefaultSlingScript#call(...)} is resource resolver
+ bindings.put(SlingScriptConstants.ATTR_SCRIPT_RESOURCE_RESOLVER, request.getResourceResolver());
+
+ return bindings;
+ }
+}
Propchange: sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java
------------------------------------------------------------------------------
svn:mime-type = text/plain
Added: sling/trunk/bundles/scripting/core/src/main/resources/scriptingvariables/ui/scriptingvariables.js
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/resources/scriptingvariables/ui/scriptingvariables.js?rev=1784700&view=auto
==============================================================================
--- sling/trunk/bundles/scripting/core/src/main/resources/scriptingvariables/ui/scriptingvariables.js (added)
+++ sling/trunk/bundles/scripting/core/src/main/resources/scriptingvariables/ui/scriptingvariables.js Tue Feb 28 08:26:34 2017
@@ -0,0 +1,74 @@
+/*
+ * Copyright 2016 The Apache Software Foundation.
+ *
+ * Licensed 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.
+ */
+(function () {
+ $(document).ready(function () {
+ $('#submitButton').on('click', function (e) {
+ e.preventDefault();
+ lookupVariables($("input[name='form.path']").val(), $("select[name='form.extension']").val());
+ });
+ });
+
+ function renderContent(variables) {
+ var myTable = "";
+ for (var engineIndex = 0; engineIndex < variables.length; engineIndex++) {
+ engineSection = variables[engineIndex];
+ myTable += "<br/><div class='ui-widget-header ui-corner-top buttonGroup' style='height: 15px'>"
+ + "<span style='float: left; margin-left: 1em;'>Variables for engine '" + engineSection.engine +"' (extensions: "+ engineSection.extensions.join() +")</span>"
+ + "</div>"
+ + "<table class='nicetable ui-widget'>" + "<tbody>"
+ + "<thead><tr><th class='ui-widget-header'>Name </th> <th class='ui-widget-header'>Class</th></tr></thead>";
+
+ for (var variableIndex = 0; variableIndex < engineSection.bindings.length; variableIndex++) {
+ myTable += produceTableRow(engineSection.bindings[variableIndex], variableIndex);
+ }
+ myTable += "</table>";
+ }
+ return myTable;
+ }
+
+ function lookupVariables(path, extension) {
+ if (/^\//.test(path)) {
+ $.ajax(appendSelectorToPath(path) + "?extension="+extension,
+ {
+ type: 'GET'
+ }
+ ).success(
+ function (data) {
+ $('#response').html(renderContent(data));
+ }
+ ).fail(
+ function () {
+ $('#response').html('No scripting context available under provided path.');
+ }
+ );
+ } else {
+ $('#response').html('Invalid path given.');
+ }
+ }
+
+ function appendSelectorToPath(path) {
+ return path + ".availablebindings.json";
+ }
+
+
+ function produceTableRow(variable, i) {
+ return "<tr class='" + (i % 2 === 0 ? "even" : "odd") + " ui-state-default'>"
+ + "<td>" + variable.name + "</td>"
+ + "<td><code>" + variable.class + "</code></td>"
+ + "</tr>";
+ }
+})();
+