Index: src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java
===================================================================
--- src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java (revision 1784538)
+++ src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java (working copy)
@@ -629,7 +629,7 @@
};
}
- private Bindings verifySlingBindings(final SlingBindings slingBindings) throws IOException {
+ Bindings verifySlingBindings(final SlingBindings slingBindings) throws IOException {
final Bindings bindings = new SimpleBindings();
Index: src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java
===================================================================
--- src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java (revision 0)
+++ src/main/java/org/apache/sling/scripting/core/impl/ScriptingVariablesConsolePlugin.java (revision 0)
@@ -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 AbstractWebConsolePlugin#spoolResource
+ *
+ * @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("");
+ pw.append("
");
+ pw.append("
");
+ pw.append("
");
+ }
+}
Index: src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java
===================================================================
--- src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java (revision 0)
+++ src/main/java/org/apache/sling/scripting/core/impl/SlingBindingsVariablesListJsonServlet.java (revision 0)
@@ -0,0 +1,168 @@
+/*
+ * 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.commons.json.JSONArray;
+import org.apache.sling.commons.json.JSONException;
+import org.apache.sling.commons.json.JSONObject;
+import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
+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");
+ JSONArray jsonArray = new JSONArray();
+ // 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 {
+ try {
+ JSONObject jsonObject = getBindingsJsonByEngineFactory(selectedScriptEngine.getFactory(), request, response);
+ jsonArray.put(jsonObject);
+ } catch (JSONException e) {
+ throw new IOException("Can not output json", e);
+ }
+ }
+ } else {
+ for (ScriptEngineFactory engineFactory : scriptEngineManager.getEngineFactories()) {
+ try {
+ JSONObject jsonObject = getBindingsJsonByEngineFactory(engineFactory, request, response);
+ jsonArray.put(jsonObject);
+ } catch (JSONException e) {
+ throw new IOException("Can not output json", e);
+ }
+ }
+ }
+ response.getWriter().print(jsonArray.toString());
+ }
+
+ private JSONObject getBindingsJsonByEngineFactory(ScriptEngineFactory engineFactory, SlingHttpServletRequest request, SlingHttpServletResponse response) throws JSONException, IOException {
+ Bindings bindings = getBindingsByEngine(engineFactory, request, response);
+ JSONArray bindingsJson = new JSONArray();
+ for (Map.Entry
entry : bindings.entrySet()) {
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("name", entry.getKey());
+ jsonObject.put("class", entry.getValue().getClass().getName());
+ bindingsJson.put(jsonObject);
+ }
+ JSONObject jsonObject = new JSONObject();
+ jsonObject.put("engine", engineFactory.getEngineName());
+ jsonObject.put("extensions", engineFactory.getExtensions());
+ jsonObject.put("bindings", bindingsJson);
+ return jsonObject;
+ }
+
+ /**
+ * Gets the {@link Bindings} object for the given {@link ScriptEngineFactory}.
+ * It only considers the default context "request".
+ *
+ * @see binding contexts(SLING-3083)
+ *
+ * @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, JSONException {
+ String context = SlingScriptAdapterFactory.BINDINGS_CONTEXT; // use default context only
+ final Collection 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;
+ }
+}
Index: src/main/resources/scriptingvariables/ui/scriptingvariables.js
===================================================================
--- src/main/resources/scriptingvariables/ui/scriptingvariables.js (revision 0)
+++ src/main/resources/scriptingvariables/ui/scriptingvariables.js (revision 0)
@@ -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 += "
"
+ + "";
+ }
+ 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 ""
+ + "| " + variable.name + " | "
+ + "" + variable.class + " | "
+ + "
";
+ }
+})();
+
Index: src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java
===================================================================
--- src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java (revision 1784515)
+++ src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java (working copy)
@@ -103,7 +103,10 @@
mavenBundle().groupId(SLING_GID).artifactId("org.apache.sling.api").versionAsInProject(),
mavenBundle().groupId(SLING_GID).artifactId("org.apache.sling.commons.mime").versionAsInProject(),
mavenBundle().groupId(SLING_GID).artifactId("org.apache.sling.commons.osgi").versionAsInProject(),
-
+ mavenBundle().groupId(SLING_GID).artifactId("org.apache.sling.commons.json").versionAsInProject(),
+ // transitive dependency of commons.json
+ mavenBundle().groupId(SLING_GID).artifactId("org.apache.sling.jcr.jcr-wrapper").version("2.0.0"),
+
mavenBundle().groupId("javax.servlet").artifactId("javax.servlet-api").versionAsInProject(),
mavenBundle().groupId("commons-io").artifactId("commons-io").versionAsInProject(),
mavenBundle().groupId("commons-lang").artifactId("commons-lang").versionAsInProject(),