Author: radu
Date: Tue Jul 14 12:01:33 2015
New Revision: 1690904

URL: http://svn.apache.org/r1690904
Log:
SLING-913 - Add a cache for pre-compiled scripts

* implemented a size-bound event-based ScriptCache that can store compilation 
results for ScriptEngines that implement Compilable
* provided a Felix web console plugin for the ScriptCache implementation so 
that cache entries can be manually removed from the cache, if
needed
* updated JavaDoc to comply with Java 1.8

Added:
    
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/CachedScript.java
    
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptCache.java
    
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptNameAware.java
    
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/ScriptNameAwareReader.java
    
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheConsolePlugin.java
    
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java
    
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachedScriptImpl.java
    
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachingMap.java
    sling/trunk/bundles/scripting/core/src/main/resources/
    sling/trunk/bundles/scripting/core/src/main/resources/scriptcache/
    sling/trunk/bundles/scripting/core/src/main/resources/scriptcache/ui/
    
sling/trunk/bundles/scripting/core/src/main/resources/scriptcache/ui/scriptcache.js
Modified:
    sling/trunk/bundles/scripting/api/pom.xml
    
sling/trunk/bundles/scripting/api/src/main/java/javax/script/ScriptEngineManager.java
    
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvider.java
    sling/trunk/bundles/scripting/core/pom.xml
    
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/DefaultSlingScript.java
    
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/LogWriter.java
    
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
    
sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java

Modified: sling/trunk/bundles/scripting/api/pom.xml
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/api/pom.xml?rev=1690904&r1=1690903&r2=1690904&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/api/pom.xml (original)
+++ sling/trunk/bundles/scripting/api/pom.xml Tue Jul 14 12:01:33 2015
@@ -54,7 +54,7 @@
               javax.script
             </Import-Package>
             <Export-Package>
-              org.apache.sling.scripting.api;version=2.2.0
+              org.apache.sling.scripting.api;version=2.3.0
             </Export-Package>
           </instructions>
         </configuration>

Modified: 
sling/trunk/bundles/scripting/api/src/main/java/javax/script/ScriptEngineManager.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/api/src/main/java/javax/script/ScriptEngineManager.java?rev=1690904&r1=1690903&r2=1690904&view=diff
==============================================================================
--- 
sling/trunk/bundles/scripting/api/src/main/java/javax/script/ScriptEngineManager.java
 (original)
+++ 
sling/trunk/bundles/scripting/api/src/main/java/javax/script/ScriptEngineManager.java
 Tue Jul 14 12:01:33 2015
@@ -73,6 +73,8 @@ public class ScriptEngineManager {
     /**
      * @deprecated use {@link #getBindings()} instaed. This method is 
introduced
      *             by the Livetribe JSR-223 implementation and is wrong.
+     *
+     * @return the bindings
      */
     @Deprecated
     public Bindings getGlobalScope() {

Modified: 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvider.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvider.java?rev=1690904&r1=1690903&r2=1690904&view=diff
==============================================================================
--- 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvider.java
 (original)
+++ 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/BindingsValuesProvider.java
 Tue Jul 14 12:01:33 2015
@@ -28,7 +28,7 @@ public interface BindingsValuesProvider
 
     /** The name of the multi-value service property that defines the 
context(s) to which 
      *  a BindingsValuesProvider applies. This service property is optional, 
if not set
-     *  the default value is {@link @DEFAULT_CONTEXT}  
+     *  the default value is {@link #DEFAULT_CONTEXT}
      */
     String CONTEXT = "context";
     

Added: 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/CachedScript.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/CachedScript.java?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/CachedScript.java
 (added)
+++ 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/CachedScript.java
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,44 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.api;
+
+import javax.script.CompiledScript;
+
+/**
+ * The {@code CachedScript} provides an abstraction on top of {@link 
CompiledScript} such that compiled scripts can be cached for further
+ * executions.
+ */
+public interface CachedScript {
+
+    /**
+     * Returns the path of the script which was compiled and cached.
+     *
+     * @return the script's path
+     */
+    String getScriptPath();
+
+    /**
+     * Returns the compiled script which can be used for further executions / 
evaluations.
+     *
+     * @return the compiled script
+     */
+    CompiledScript getCompiledScript();
+
+}

Added: 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptCache.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptCache.java?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptCache.java
 (added)
+++ 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptCache.java
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.api;
+
+/**
+ * The {@code ScriptCache} service interface defines a cache for compiled 
scripts. Implementations of this interface should be thread-safe.
+ */
+public interface ScriptCache {
+
+    /**
+     * Retrieves the {@link CachedScript} corresponding to the script 
accessible from the {@code scriptPath}.
+     *
+     * @param scriptPath the path from where the script can be accessed
+     * @return the {@link CachedScript} if one exists, {@code null} otherwise
+     */
+    CachedScript getScript(String scriptPath);
+
+    /**
+     * Stores a {@link CachedScript} in the cache. If a previous version of it 
exist in the cache it is overridden.
+     *
+     * @param script the {@link CachedScript} that should be stored in the 
cache
+     */
+    void putScript(CachedScript script);
+
+    /**
+     * Empties the cache.
+     */
+    void clear();
+
+    /**
+     * Removes the script identified by {@code scriptPath} from the cache.
+     *
+     * @param scriptPath the path from where the script can be accessed
+     * @return {@code true} if a script was cached from that path and was 
removed, {@code false} otherwise
+     */
+    boolean removeScript(String scriptPath);
+
+}

Added: 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptNameAware.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptNameAware.java?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptNameAware.java
 (added)
+++ 
sling/trunk/bundles/scripting/api/src/main/java/org/apache/sling/scripting/api/ScriptNameAware.java
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,34 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.api;
+
+/**
+ * Marker interface for various {@link java.io.Reader}s from which a script's 
name can be obtained.
+ */
+public interface ScriptNameAware {
+
+    /**
+     * Returns the name of the script provided by a marked {@link 
java.io.Reader} implementation.
+     *
+     * @return the script's name
+     */
+    String getScriptName();
+
+}

Modified: sling/trunk/bundles/scripting/core/pom.xml
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/pom.xml?rev=1690904&r1=1690903&r2=1690904&view=diff
==============================================================================
--- sling/trunk/bundles/scripting/core/pom.xml (original)
+++ sling/trunk/bundles/scripting/core/pom.xml Tue Jul 14 12:01:33 2015
@@ -61,7 +61,7 @@
                 <configuration>
                     <instructions>
                         <Export-Package>
-                            org.apache.sling.scripting.core;version=2.0.8,
+                            org.apache.sling.scripting.core;version=2.1.0,
                             
org.apache.sling.scripting.core.servlet;version=1.0.0
                         </Export-Package>
                         <Private-Package>
@@ -136,7 +136,13 @@
         <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.scripting.api</artifactId>
-            <version>2.1.6</version>
+            <version>2.1.7-SNAPSHOT</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.threads</artifactId>
+            <version>3.1.0</version>
             <scope>provided</scope>
         </dependency>
 
@@ -156,6 +162,24 @@
             <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.scr.annotations</artifactId>
         </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.webconsole</artifactId>
+            <version>3.1.8</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
 
         <dependency>
             <groupId>org.slf4j</groupId>

Added: 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/ScriptNameAwareReader.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/ScriptNameAwareReader.java?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/ScriptNameAwareReader.java
 (added)
+++ 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/ScriptNameAwareReader.java
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,53 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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;
+
+
+import java.io.FilterReader;
+import java.io.Reader;
+
+import org.apache.sling.scripting.api.ScriptNameAware;
+
+/**
+ * The {@code ScriptNameAwareReader} is a {@link FilterReader} marked with the 
{@link ScriptNameAware} interface. This reader allows
+ * retrieving the contained script's name.
+ */
+public final class ScriptNameAwareReader extends FilterReader implements 
ScriptNameAware {
+
+    private String scriptName;
+
+    /**
+     * Creates a {@code ScriptNameAwareReader} based on another {@link Reader}.
+     *
+     * @param in         the base {@link Reader}
+     * @param scriptName the script's name
+     */
+    public ScriptNameAwareReader(Reader in, String scriptName) {
+        super(in);
+        this.scriptName = scriptName;
+    }
+
+    @Override
+    public String getScriptName() {
+        return scriptName;
+    }
+
+
+}

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=1690904&r1=1690903&r2=1690904&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 Jul 14 12:01:33 2015
@@ -28,6 +28,7 @@ import static org.apache.sling.api.scrip
 import static org.apache.sling.api.scripting.SlingBindings.SLING;
 
 import java.io.BufferedReader;
+import java.io.FilterReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
@@ -46,6 +47,8 @@ import java.util.Map;
 import java.util.Set;
 
 import javax.script.Bindings;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
 import javax.script.Invocable;
 import javax.script.ScriptContext;
 import javax.script.ScriptEngine;
@@ -72,6 +75,11 @@ import org.apache.sling.api.scripting.Sl
 import org.apache.sling.api.scripting.SlingScriptConstants;
 import org.apache.sling.api.scripting.SlingScriptHelper;
 import org.apache.sling.scripting.api.BindingsValuesProvider;
+import org.apache.sling.scripting.api.CachedScript;
+import org.apache.sling.scripting.api.ScriptCache;
+import org.apache.sling.scripting.api.ScriptNameAware;
+import org.apache.sling.scripting.core.ScriptNameAwareReader;
+import org.apache.sling.scripting.core.impl.helper.CachedScriptImpl;
 import org.apache.sling.scripting.core.impl.helper.ProtectedBindings;
 import org.osgi.framework.BundleContext;
 import org.slf4j.Logger;
@@ -90,6 +98,7 @@ class DefaultSlingScript implements Slin
         new HashSet<String>(Arrays.asList(REQUEST, RESPONSE, READER, SLING, 
RESOURCE, OUT, LOG));
 
     /** The resource pointing to the script. */
+
     private final Resource scriptResource;
 
     /** The name of the script (the resource path) */
@@ -116,6 +125,9 @@ class DefaultSlingScript implements Slin
     /** The cache for services. */
     private final ServiceCache cache;
 
+    /* The cache for compiled scripts. */
+    private final ScriptCache scriptCache;
+
     /**
      * Constructor
      * @param bundleContext The bundle context
@@ -128,12 +140,14 @@ class DefaultSlingScript implements Slin
             final Resource scriptResource,
             final ScriptEngine scriptEngine,
             final Collection<BindingsValuesProvider> bindingsValuesProviders,
-            final ServiceCache cache) {
+            final ServiceCache cache,
+            final ScriptCache scriptCache) {
         this.scriptResource = scriptResource;
         this.scriptEngine = scriptEngine;
         this.bundleContext = bundleContext;
         this.bindingsValuesProviders = bindingsValuesProviders;
         this.cache = cache;
+        this.scriptCache = scriptCache;
         this.scriptName = this.scriptResource.getPath();
         // Now know how to get the input stream, we still have to decide
         // on the encoding of the stream's data. Primarily we assume it is
@@ -358,7 +372,22 @@ class DefaultSlingScript implements Slin
             }
 
             // evaluate the script
-            final Object result = scriptEngine.eval(reader, ctx);
+            final Object result;
+            if (method == null && this.scriptEngine instanceof Compilable) {
+                CachedScript cachedScript = scriptCache.getScript(scriptName);
+                if (cachedScript == null) {
+                    ScriptNameAwareReader snReader = new 
ScriptNameAwareReader(reader, scriptName);
+                    CompiledScript compiledScript = ((Compilable) 
scriptEngine).compile(snReader);
+                    cachedScript = new CachedScriptImpl(scriptName, 
compiledScript);
+                    scriptCache.putScript(cachedScript);
+                    LOGGER.debug("Adding {} to the script cache.", scriptName);
+                } else {
+                    LOGGER.debug("Script {} was already cached.", scriptName);
+                }
+                result = cachedScript.getCompiledScript().eval(ctx);
+            } else {
+                result = scriptEngine.eval(reader, ctx);
+            }
 
             // call method - if supplied and script engine supports direct 
invocation
             if ( method != null && (this.scriptEngine instanceof Invocable)) {

Modified: 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/LogWriter.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/LogWriter.java?rev=1690904&r1=1690903&r2=1690904&view=diff
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/LogWriter.java
 (original)
+++ 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/LogWriter.java
 Tue Jul 14 12:01:33 2015
@@ -41,6 +41,8 @@ public class LogWriter extends Writer {
 
     /**
      * Creates a writer based on the given logger.
+     *
+     * @param logger the logger
      */
     public LogWriter(Logger logger) {
         this.logger = logger;

Added: 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheConsolePlugin.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheConsolePlugin.java?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheConsolePlugin.java
 (added)
+++ 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheConsolePlugin.java
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,141 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+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;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.apache.sling.scripting.api.ScriptCache;
+import org.osgi.framework.Constants;
+
+@Component
+@Service
+@Properties({
+        @Property(name = Constants.SERVICE_DESCRIPTION, value = "Script 
Cache"),
+        @Property(name = Constants.SERVICE_VENDOR, value = "The Apache 
Software Foundation"),
+        @Property(name = WebConsoleConstants.PLUGIN_LABEL, value = 
ScriptCacheConsolePlugin.CONSOLE_LABEL),
+        @Property(name = WebConsoleConstants.PLUGIN_TITLE, value = 
ScriptCacheConsolePlugin.CONSOLE_TITLE),
+        @Property(name = "felix.webconsole.category", value = "Sling")
+})
+public class ScriptCacheConsolePlugin extends AbstractWebConsolePlugin {
+
+    public static final String CONSOLE_LABEL = "scriptcache";
+    public static final String CONSOLE_TITLE = "Script Cache Status";
+    public static final String RESOURCES = CONSOLE_LABEL + "/ui";
+
+    private static final String SCRIPTCACHE_JS = "scriptcache.js";
+    private static final String CTYPE_JAVASCRIPT = "application/javascript";
+    private static final String POST_SCRIPT = "script";
+
+    @Reference
+    private ScriptCache scriptCache = null;
+
+    public ScriptCacheConsolePlugin() {
+        super();
+    }
+
+    @Override
+    public String getTitle() {
+        return CONSOLE_TITLE;
+    }
+
+    @Override
+    public String getLabel() {
+        return CONSOLE_LABEL;
+    }
+
+    @Override
+    protected void renderContent(HttpServletRequest httpServletRequest, 
HttpServletResponse httpServletResponse)
+            throws ServletException, IOException {
+        if (scriptCache instanceof ScriptCacheImpl) {
+            ScriptCacheImpl scriptCacheImpl = (ScriptCacheImpl) scriptCache;
+            List<String> scripts = new 
ArrayList<String>(scriptCacheImpl.getCachedScripts());
+            StringBuilder sb = new StringBuilder();
+            sb.append("<script type='text/javascript' 
src='").append(RESOURCES).append("/").append(SCRIPTCACHE_JS).append("'></script>");
+            sb.append("<div id='cached-scripts' class='ui-widget statline'>");
+            if (scripts.size() > 0) {
+                Collections.sort(scripts);
+                sb.append("<p class='ui-widget-header'>Cached Scripts</p>");
+                sb.append("<table class='nicetable ui-widget-content'>");
+                int i = 0;
+                for (String script : scripts) {
+                    sb.append("<tr class='").append(i % 2 == 0 ? "even" : 
"odd").append(" ui-state-default'><td>").append(++i).append
+                            
("<td><code>").append(script).append("</code></td><td><button type='button' " +
+                            
"data-script='").append(script).append("'>Remove</button></td></tr>");
+                }
+                sb.append("<tr><td colspan='3'><button type='button' 
id='clearcache'>Clear Cache</button></td></tr>");
+                sb.append("</table>");
+
+            } else {
+                sb.append("<p class='ui-state-highlight'>The Script Cache 
doesn't contain any scripts.</p>");
+            }
+            sb.append("</div>");
+            httpServletResponse.getWriter().write(sb.toString());
+        }
+    }
+
+    @Override
+    protected void doGet(HttpServletRequest request, HttpServletResponse 
response) throws ServletException, IOException {
+        if (request.getRequestURI().endsWith(RESOURCES + "/" + 
SCRIPTCACHE_JS)) {
+            response.setContentType(CTYPE_JAVASCRIPT);
+            IOUtils.copy(getClass().getResourceAsStream("/" + RESOURCES + "/" 
+ SCRIPTCACHE_JS), response.getOutputStream());
+        } else {
+            super.doGet(request, response);
+        }
+    }
+
+    @Override
+    protected void doPost(HttpServletRequest req, HttpServletResponse resp) 
throws ServletException, IOException {
+        String script = req.getParameter(POST_SCRIPT);
+        if (StringUtils.isNotEmpty(script)) {
+            if ("all".equals(script)) {
+                scriptCache.clear();
+                renderContent(req, resp);
+            } else {
+                boolean success = scriptCache.removeScript(script);
+                if (success) {
+                    renderContent(req, resp);
+                }
+            }
+            resp.setStatus(HttpServletResponse.SC_OK);
+        } else {
+            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
+        }
+
+    }
+}
+
+

Added: 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java
 (added)
+++ 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/ScriptCacheImpl.java
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,302 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.lang.ref.SoftReference;
+import java.util.Arrays;
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import javax.script.Compilable;
+import javax.script.CompiledScript;
+import javax.script.ScriptEngine;
+import javax.script.ScriptEngineFactory;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Deactivate;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.PropertyUnbounded;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingConstants;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceResolverFactory;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.commons.threads.ThreadPool;
+import org.apache.sling.commons.threads.ThreadPoolManager;
+import org.apache.sling.scripting.api.CachedScript;
+import org.apache.sling.scripting.api.ScriptCache;
+import org.apache.sling.scripting.core.impl.helper.CachingMap;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@Component(
+        metatype = true,
+        label = "Apache Sling Script Cache",
+        description = "The Script Cache is useful for running previously 
compiled scripts."
+)
+@Properties({
+        @Property(
+                name = ScriptCacheImpl.PROP_CACHE_SIZE,
+                intValue = ScriptCacheImpl.DEFAULT_CACHE_SIZE,
+                label = "Cache Size",
+                description = "The Cache Size defines the maximum number of 
compiled script references that will be stored in the cache's" +
+                        " internal map."
+        ),
+        @Property(
+                name = ScriptCacheImpl.PROP_ADDITIONAL_EXTENSIONS,
+                value = "",
+                label = "Additional Extensions",
+                description = "Scripts from the search paths with these 
extensions will also be monitored so that changes to them will " +
+                        "clean the cache if the cache contains them.",
+                unbounded = PropertyUnbounded.ARRAY
+        )
+})
+@Service(ScriptCache.class)
+@Reference(
+        name = "scriptEngineFactory",
+        cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE,
+        referenceInterface = ScriptEngineFactory.class,
+        policy = ReferencePolicy.DYNAMIC
+)
+@SuppressWarnings("unused")
+/**
+ * The {@code ScriptCache} stores information about {@link CompiledScript} 
instances evaluated by various {@link ScriptEngine}s that
+ * implement the {@link Compilable} interface.
+ */
+public class ScriptCacheImpl implements EventHandler, ScriptCache {
+
+    private static final Logger LOGGER = 
LoggerFactory.getLogger(ScriptCacheImpl.class);
+
+    public static final int DEFAULT_CACHE_SIZE = 65536;
+    public static final String PROP_CACHE_SIZE = 
"org.apache.sling.scripting.cache.size";
+    public static final String PROP_ADDITIONAL_EXTENSIONS = 
"org.apache.sling.scripting.cache.additional_extensions";
+
+    private BundleContext bundleContext;
+    private Map<String, SoftReference<CachedScript>> internalMap;
+    private ServiceRegistration eventHandlerServiceRegistration = null;
+    private Set<String> extensions = new HashSet<String>();
+    private String[] additionalExtensions = new String[]{};
+
+    // use a static policy so that we can reconfigure the watched script files 
if the search paths are changed
+    @Reference(policy = ReferencePolicy.STATIC)
+    private ResourceResolverFactory rrf = null;
+
+    @Reference
+    private ThreadPoolManager threadPoolManager = null;
+
+    private ThreadPool threadPool;
+    private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
+    private final Lock readLock = rwl.readLock();
+    private final Lock writeLock = rwl.writeLock();
+    boolean active = false;
+
+    public ScriptCacheImpl() {
+        internalMap = new CachingMap<CachedScript>(DEFAULT_CACHE_SIZE);
+    }
+
+    @Override
+    public CachedScript getScript(String scriptPath) {
+        readLock.lock();
+        SoftReference<CachedScript> reference = null;
+        try {
+            reference = internalMap.get(scriptPath);
+        } finally {
+            readLock.unlock();
+        }
+        return reference != null ? reference.get() : null;
+    }
+
+    @Override
+    public void putScript(CachedScript script) {
+        SoftReference<CachedScript> reference = new 
SoftReference<CachedScript>(script);
+        writeLock.lock();
+        try {
+            internalMap.put(script.getScriptPath(), reference);
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public void clear() {
+        writeLock.lock();
+        try {
+            internalMap.clear();
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public boolean removeScript(String scriptPath) {
+        writeLock.lock();
+        try {
+            SoftReference<CachedScript> reference = 
internalMap.remove(scriptPath);
+            if (reference != null) {
+                return true;
+            }
+            return false;
+        } finally {
+            writeLock.unlock();
+        }
+    }
+
+    @Override
+    public void handleEvent(final Event event) {
+        /**
+         * since the events trigger a synchronised map operation (remove in 
this case) we should handle events asynchronously so that we
+         * don't block event processing
+         */
+        final String topic = event.getTopic();
+        if (SlingConstants.TOPIC_RESOURCE_CHANGED.equals(topic) || 
SlingConstants.TOPIC_RESOURCE_REMOVED.equals(topic)) {
+            Runnable eventTask = new Runnable() {
+                @Override
+                public void run() {
+                    String path = (String) 
event.getProperty(SlingConstants.PROPERTY_PATH);
+                    writeLock.lock();
+                    try {
+                        internalMap.remove(path);
+                        LOGGER.debug("Detected script change for {} - removed 
entry from the cache.", path);
+                    } finally {
+                        writeLock.unlock();
+                    }
+                }
+            };
+            threadPool.execute(eventTask);
+        }
+    }
+
+    protected Set<String> getCachedScripts() {
+        readLock.lock();
+        try {
+            return internalMap.keySet();
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    @Activate
+    @SuppressWarnings("unused")
+    protected void activate(ComponentContext componentContext) {
+        threadPool = threadPoolManager.get("Script Cache Thread Pool");
+        bundleContext = componentContext.getBundleContext();
+        Dictionary properties = componentContext.getProperties();
+        additionalExtensions = 
PropertiesUtil.toStringArray(properties.get(PROP_ADDITIONAL_EXTENSIONS));
+        int newMaxCacheSize = 
PropertiesUtil.toInteger(properties.get(PROP_CACHE_SIZE), DEFAULT_CACHE_SIZE);
+        if (newMaxCacheSize != DEFAULT_CACHE_SIZE) {
+            // change the map only if there's a configuration change regarding 
the cache's max size
+            CachingMap<CachedScript> newMap = new 
CachingMap<CachedScript>(newMaxCacheSize);
+            newMap.putAll(internalMap);
+            internalMap = newMap;
+        }
+        configureCache();
+        active = true;
+    }
+
+    @SuppressWarnings("unchecked")
+    private void configureCache() {
+        writeLock.lock();
+        ResourceResolver adminResolver = null;
+        try {
+            if (eventHandlerServiceRegistration != null) {
+                eventHandlerServiceRegistration.unregister();
+            }
+            internalMap.clear();
+            extensions.addAll(Arrays.asList(additionalExtensions));
+            if (extensions.size() > 0) {
+                adminResolver = rrf.getAdministrativeResourceResolver(null);
+                StringBuilder eventHandlerFilter = new StringBuilder("(|");
+                for (String searchPath : adminResolver.getSearchPath()) {
+                    for (String extension : extensions) {
+                        
eventHandlerFilter.append("(path=").append(searchPath).append("**/*.").append(extension).append(")");
+                    }
+                }
+                eventHandlerFilter.append(")");
+                Dictionary eventHandlerProperties = new Hashtable();
+                eventHandlerProperties.put(EventConstants.EVENT_FILTER, 
eventHandlerFilter.toString());
+                eventHandlerProperties.put(EventConstants.EVENT_TOPIC,
+                        new String[]{SlingConstants.TOPIC_RESOURCE_CHANGED, 
SlingConstants.TOPIC_RESOURCE_REMOVED});
+                eventHandlerServiceRegistration = 
bundleContext.registerService(EventHandler.class.getName(), this, 
eventHandlerProperties);
+            }
+        } catch (LoginException e) {
+            LOGGER.error("Unable to set automated cache invalidation for the 
ScriptCache.", e);
+        } finally {
+            if (adminResolver != null) {
+                adminResolver.close();
+            }
+            writeLock.unlock();
+        }
+    }
+
+    @Deactivate
+    @SuppressWarnings("unused")
+    protected void deactivate(ComponentContext componentContext) {
+        internalMap.clear();
+        if (eventHandlerServiceRegistration != null) {
+            eventHandlerServiceRegistration.unregister();
+            eventHandlerServiceRegistration = null;
+        }
+        if (threadPool != null) {
+            threadPoolManager.release(threadPool);
+            threadPool = null;
+        }
+        active = false;
+    }
+
+    protected void bindScriptEngineFactory(ScriptEngineFactory 
scriptEngineFactory, Map<String, Object> properties) {
+        ScriptEngine engine = scriptEngineFactory.getScriptEngine();
+        if (engine instanceof Compilable) {
+            /**
+             * we only care about creating an EventHandler that monitors 
scripts generated by script engines which implement Compilable
+             */
+            for (String extension : scriptEngineFactory.getExtensions()) {
+                extensions.add(extension);
+            }
+            if (active) {
+                configureCache();
+            }
+        }
+    }
+
+    protected void unbindScriptEngineFactory(ScriptEngineFactory 
scriptEngineFactory, Map<String, Object> properties) {
+        for (String extension : scriptEngineFactory.getExtensions()) {
+            extensions.remove(extension);
+        }
+        if (active) {
+            configureCache();
+        }
+    }
+}

Modified: 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java?rev=1690904&r1=1690903&r2=1690904&view=diff
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
 (original)
+++ 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/SlingScriptAdapterFactory.java
 Tue Jul 14 12:01:33 2015
@@ -31,6 +31,7 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.commons.mime.MimeTypeProvider;
 import org.apache.sling.scripting.api.BindingsValuesProvider;
 import org.apache.sling.scripting.api.BindingsValuesProvidersByContext;
+import org.apache.sling.scripting.api.ScriptCache;
 import org.apache.sling.scripting.core.impl.helper.SlingScriptEngineManager;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.component.ComponentContext;
@@ -73,6 +74,9 @@ public class SlingScriptAdapterFactory i
     @Reference
     private BindingsValuesProvidersByContext bindingsValuesProviderTracker;
 
+    @Reference
+    private ScriptCache scriptCache;
+
     // ---------- AdapterFactory 
-----------------------------------------------
 
     @SuppressWarnings("unchecked")
@@ -88,7 +92,7 @@ public class SlingScriptAdapterFactory i
                     
bindingsValuesProviderTracker.getBindingsValuesProviders(engine.getFactory(), 
BINDINGS_CONTEXT);
             // unchecked cast
             return (AdapterType) new DefaultSlingScript(this.bundleContext,
-                    resource, engine, bindingsValuesProviders, 
this.serviceCache);
+                    resource, engine, bindingsValuesProviders, 
this.serviceCache, scriptCache);
         }
 
         return null;

Added: 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachedScriptImpl.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachedScriptImpl.java?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachedScriptImpl.java
 (added)
+++ 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachedScriptImpl.java
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.helper;
+
+import javax.script.CompiledScript;
+
+import org.apache.sling.scripting.api.CachedScript;
+
+public class CachedScriptImpl implements CachedScript {
+
+    private String scriptPath;
+    private CompiledScript compiledScript;
+
+    public CachedScriptImpl(String scriptPath, CompiledScript compiledScript) {
+        this.scriptPath = scriptPath;
+        this.compiledScript = compiledScript;
+    }
+
+    public String getScriptPath() {
+        return scriptPath;
+    }
+
+    public CompiledScript getCompiledScript() {
+        return compiledScript;
+    }
+}

Added: 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachingMap.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachingMap.java?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachingMap.java
 (added)
+++ 
sling/trunk/bundles/scripting/core/src/main/java/org/apache/sling/scripting/core/impl/helper/CachingMap.java
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,54 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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.helper;
+
+import java.lang.ref.SoftReference;
+import java.util.LinkedHashMap;
+import java.util.Map;
+
+/**
+ * <p>
+ * The {@code CachingMap} class offers an implementation of a {@link 
LinkedHashMap} that can be used for caches. The maps' values are
+ * {@link SoftReference}s, such that garbage collection can be performed on 
the cache, if needed.
+ * </p>
+ * <p>
+ * Read / write operations are <i>NOT</i> synchronised.
+ * </p>
+ *
+ * @param <T> the type to which {@link SoftReference}s will be kept
+ */
+public class CachingMap<T> extends LinkedHashMap<String, SoftReference<T>> {
+
+    private int capacity;
+
+    /**
+     * Creates a caching map with a maximum capacity equal to the {@code 
capacity} parameter.
+     *
+     * @param capacity the maximum capacity; if {@code capacity < 1} then this 
map will always remove the latest added element
+     */
+    public CachingMap(int capacity) {
+        this.capacity = capacity;
+    }
+
+    @Override
+    protected boolean removeEldestEntry(Map.Entry<String, SoftReference<T>> 
eldest) {
+        return size() > capacity;
+    }
+}

Added: 
sling/trunk/bundles/scripting/core/src/main/resources/scriptcache/ui/scriptcache.js
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/main/resources/scriptcache/ui/scriptcache.js?rev=1690904&view=auto
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/main/resources/scriptcache/ui/scriptcache.js
 (added)
+++ 
sling/trunk/bundles/scripting/core/src/main/resources/scriptcache/ui/scriptcache.js
 Tue Jul 14 12:01:33 2015
@@ -0,0 +1,51 @@
+/*******************************************************************************
+ * 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
+ * <p/>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p/>
+ * 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() {
+        $('div#cached-scripts button[id!="clearcache"]').on('click', function 
(e) {
+            e.preventDefault();
+            var script = $(this).data('script');
+            clearCache(script);
+        });
+
+        $('#clearcache').on('click', function (e) {
+            e.preventDefault();
+            clearCache('all');
+        });
+    });
+
+    function clearCache(script) {
+        $.ajax(
+            {
+                type: 'POST',
+                data: {
+                    script: script
+                }
+            }
+        ).success(
+            function (data) {
+                $('#cached-scripts').replaceWith(data);
+            }
+        ).fail(
+            function () {
+                alert("Unable to clear " + (script === 'all' ? 'cache' : 
'script ' + script));
+            }
+        );
+    }
+})();
\ No newline at end of file

Modified: 
sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java?rev=1690904&r1=1690903&r2=1690904&view=diff
==============================================================================
--- 
sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java
 (original)
+++ 
sling/trunk/bundles/scripting/core/src/test/java/org/apache/sling/scripting/core/impl/BindingsValuesProvidersByContextIT.java
 Tue Jul 14 12:01:33 2015
@@ -57,15 +57,15 @@ import org.osgi.framework.ServiceRegistr
 
 @RunWith(PaxExam.class)
 public class BindingsValuesProvidersByContextIT {
-    
+
     @Inject
     private BindingsValuesProvidersByContext bvpProvider;
-    
+
     @Inject
     private BundleContext bundleContext;
-    
+
     private final List<ServiceRegistration> regs = new 
ArrayList<ServiceRegistration>();
-    
+
     @org.ops4j.pax.exam.Configuration
     public Option[] config() {
         final String localRepo = System.getProperty("maven.repo.local", "");
@@ -75,7 +75,7 @@ public class BindingsValuesProvidersByCo
         if(!bundleFile.canRead()) {
             throw new IllegalArgumentException( "Cannot read from bundle file 
" + bundleFile.getAbsolutePath());
         }
-        
+
         return options(
                 when( localRepo.length() > 0 ).useOptions(
                         
systemProperty("org.ops4j.pax.url.mvn.localRepository").value(localRepo)
@@ -84,30 +84,34 @@ public class BindingsValuesProvidersByCo
                         bundle(bundleFile.toURI().toString()),
                         mavenBundle("org.apache.felix", 
"org.apache.felix.scr", "1.6.2"),
                         mavenBundle("org.apache.felix", 
"org.apache.felix.eventadmin", "1.3.2"),
-                        
-                        mavenBundle("org.apache.sling", 
"org.apache.sling.scripting.api", "2.1.6"),
+                        mavenBundle("org.apache.felix", 
"org.apache.felix.webconsole", "3.1.8"),
+
+                        mavenBundle("org.apache.sling", 
"org.apache.sling.scripting.api", "2.1.7-SNAPSHOT"),
+                        mavenBundle("org.apache.sling", 
"org.apache.sling.commons.threads", "3.1.0"),
                         mavenBundle("org.apache.sling", 
"org.apache.sling.api", "2.4.2"),
                         mavenBundle("org.apache.sling", 
"org.apache.sling.commons.mime", "2.1.4"),
                         mavenBundle("org.apache.sling", 
"org.apache.sling.commons.osgi", "2.2.0"),
-                        
-                        mavenBundle("org.mortbay.jetty", "servlet-api-2.5", 
"6.1.14")
+
+                        mavenBundle("org.mortbay.jetty", "servlet-api-2.5", 
"6.1.14"),
+                        mavenBundle("commons-io", "commons-io", "2.4"),
+                        mavenBundle("commons-lang", "commons-lang", "2.4")
                 ),
                 junitBundles()
                 );
     }
-    
+
     @Before
     public void setup() {
         regs.clear();
     }
-    
+
     @After
     public void cleanup() {
         for(ServiceRegistration reg : regs) {
             reg.unregister();
         }
     }
-    
+
 
     private Dictionary<String, Object> getProperties(String context, String 
engineName) {
         final Dictionary<String, Object> props = new Hashtable<String, 
Object>();
@@ -126,21 +130,21 @@ public class BindingsValuesProvidersByCo
             public String toString() {
                 return id;
             }
-            
+
             public void addBindings(Bindings b) {
             }
         };
-        
+
         
regs.add(bundleContext.registerService(BindingsValuesProvider.class.getName(), 
bvp, getProperties(context, engineName)));
     }
-    
+
     private void addBVPWithServiceRanking(final String id, String context, 
String engineName, int serviceRanking) {
         final BindingsValuesProvider bvp = new BindingsValuesProvider() {
             @Override
             public String toString() {
                 return id;
             }
-            
+
             public void addBindings(Bindings b) {
             }
         };
@@ -148,7 +152,7 @@ public class BindingsValuesProvidersByCo
         properties.put(Constants.SERVICE_RANKING, serviceRanking);
         
regs.add(bundleContext.registerService(BindingsValuesProvider.class.getName(), 
bvp, properties));
     }
-    
+
     private void addMap(final String id, String context, String engineName) {
         final Map<String, Object> result = new HashMap<String, Object>() {
             private static final long serialVersionUID = 1L;
@@ -158,65 +162,65 @@ public class BindingsValuesProvidersByCo
                 return "M_" + id;
             }
         };
-        
+
         regs.add(bundleContext.registerService(Map.class.getName(), result, 
getProperties(context, engineName)));
     }
-    
+
     private ScriptEngineFactory factory(final String engineName) {
         return new ScriptEngineFactory() {
-            
+
             public ScriptEngine getScriptEngine() {
                 return null;
             }
-            
+
             public String getProgram(String... arg0) {
                 return null;
             }
-            
+
             public Object getParameter(String arg0) {
                 return null;
             }
-            
+
             public String getOutputStatement(String arg0) {
                 return null;
             }
-            
+
             public List<String> getNames() {
                 final List<String> names = new ArrayList<String>();
                 names.add(engineName);
                 return names;
             }
-            
+
             public List<String> getMimeTypes() {
                 return null;
             }
-            
+
             public String getMethodCallSyntax(String arg0, String arg1, 
String... arg2) {
                 return null;
             }
-            
+
             public String getLanguageVersion() {
                 return null;
             }
-            
+
             public String getLanguageName() {
                 return null;
             }
-            
+
             public List<String> getExtensions() {
                 return null;
             }
-            
+
             public String getEngineVersion() {
                 return null;
             }
-            
+
             public String getEngineName() {
                 return engineName;
             }
         };
     }
-    
+
     private String asString(Collection<?> data, boolean sortList) {
         final List<String> maybeSorted = new ArrayList<String>();
         for(Object o : data) {
@@ -225,7 +229,7 @@ public class BindingsValuesProvidersByCo
         if(sortList) {
             Collections.sort(maybeSorted);
         }
-        
+
         final StringBuilder sb = new StringBuilder();
         for(String str : maybeSorted) {
             if(sb.length() > 0) {
@@ -235,11 +239,11 @@ public class BindingsValuesProvidersByCo
         }
         return sb.toString();
     }
-    
+
     private String asString(Collection<?> data) {
         return asString(data, true);
     }
-    
+
     @Test
     public void testAny() {
         addBVP("one", null, "js");
@@ -247,15 +251,15 @@ public class BindingsValuesProvidersByCo
         addBVP("three", null, "*");
         addBVP("four", null, "ANY");
         addBVP("five", null, "basic");
-        
+
         assertEquals("four,one,three,two", 
asString(bvpProvider.getBindingsValuesProviders(factory("js"), null)));
         assertEquals("five,four,three,two", 
asString(bvpProvider.getBindingsValuesProviders(factory("basic"), null)));
         assertEquals("four,three,two", 
asString(bvpProvider.getBindingsValuesProviders(factory("other"), null)));
-        
+
         final String unsorted = 
asString(bvpProvider.getBindingsValuesProviders(factory("js"), null), false);
         assertTrue("Expecting js language-specific BVP at the end", 
unsorted.endsWith("one"));
     }
-    
+
     @Test
     public void testContextsAndLanguages() {
         addBVP("foo", null, "js");
@@ -272,11 +276,11 @@ public class BindingsValuesProvidersByCo
         assertEquals("o1,o2,o3", 
asString(bvpProvider.getBindingsValuesProviders(factory("js"), "other")));
         assertEquals("o4,python", 
asString(bvpProvider.getBindingsValuesProviders(factory("python"), "python")));
         assertEquals("", 
asString(bvpProvider.getBindingsValuesProviders(factory("js"), 
"unusedContext")));
-        
+
         final String unsorted = 
asString(bvpProvider.getBindingsValuesProviders(factory("python"), "python"), 
false);
         assertTrue("Expecting python language-specific BVP at the end", 
unsorted.endsWith("python"));
     }
-    
+
     @Test
     public void testMapsAndBvps() {
         addBVP("foo", null, "js");
@@ -293,11 +297,11 @@ public class BindingsValuesProvidersByCo
         assertEquals("M_o1,M_o3,o2", 
asString(bvpProvider.getBindingsValuesProviders(factory("js"), "other")));
         assertEquals("", 
asString(bvpProvider.getBindingsValuesProviders(factory("js"), 
"unusedContext")));
         assertEquals("M_python,o4", 
asString(bvpProvider.getBindingsValuesProviders(factory("python"), "python")));
-        
+
         final String unsorted = 
asString(bvpProvider.getBindingsValuesProviders(factory("python"), "python"), 
false);
         assertTrue("Expecting python language-specific BVP at the end", 
unsorted.endsWith("M_python"));
     }
-    
+
     @Test
     public void testBVPsWithServiceRankingA() {
         addBVPWithServiceRanking("last", null, "js", Integer.MAX_VALUE);
@@ -305,7 +309,7 @@ public class BindingsValuesProvidersByCo
         addBVPWithServiceRanking("first", null, "js", Integer.MIN_VALUE);
         assertEquals("first,second,last", 
asString(bvpProvider.getBindingsValuesProviders(factory("js"), null), false));
     }
-    
+
     @Test
     public void testBVPsWithServiceRankingB() {
         addBVPWithServiceRanking("first", null, "js", Integer.MIN_VALUE);
@@ -313,7 +317,7 @@ public class BindingsValuesProvidersByCo
         addBVPWithServiceRanking("last", null, "js", Integer.MAX_VALUE);
         assertEquals("first,second,last", 
asString(bvpProvider.getBindingsValuesProviders(factory("js"), null), false));
     }
-    
+
     @Test
     public void testBVPsWithServiceRankingC() {
         addBVPWithServiceRanking("second", "request", "js", 0);


Reply via email to