Author: cziegeler
Date: Tue Jun 30 12:53:14 2009
New Revision: 789698

URL: http://svn.apache.org/viewvc?rev=789698&view=rev
Log:
SLING-1027 : First implementation of a configurable cache for the script 
resolution. 

Modified:
    
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
    
sling/trunk/bundles/servlets/resolver/src/main/resources/OSGI-INF/metatype/metatype.properties

Modified: 
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java?rev=789698&r1=789697&r2=789698&view=diff
==============================================================================
--- 
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
 (original)
+++ 
sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java
 Tue Jun 30 12:53:14 2009
@@ -32,6 +32,7 @@
 import java.util.Hashtable;
 import java.util.List;
 import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
 
 import javax.jcr.Credentials;
 import javax.jcr.RepositoryException;
@@ -72,6 +73,8 @@
 import org.osgi.framework.ServiceReference;
 import org.osgi.framework.ServiceRegistration;
 import org.osgi.service.component.ComponentContext;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventHandler;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -92,9 +95,11 @@
  * @scr.service
  * @scr.reference name="Servlet" interface="javax.servlet.Servlet"
  *                cardinality="0..n" policy="dynamic"
+ * @scr.property name="event.topics" value="org/apache/sling/api/resource/*"
+ *               private="true"
  */
 public class SlingServletResolver implements ServletResolver,
-        SlingScriptResolver, ErrorHandler {
+        SlingScriptResolver, ErrorHandler, EventHandler {
 
     /** default log */
     private final Logger log = LoggerFactory.getLogger(getClass());
@@ -109,9 +114,17 @@
      */
     public static final String PROP_SCRIPT_USER = "servletresolver.scriptUser";
 
+    /**
+     * @scr.property valueRef="DEFAULT_CACHE_SIZE"
+     */
+    public static final String PROP_CACHE_SIZE = "servletresolver.cacheSize";
+
     /** The default servlet root is the first search path (which is usally 
/apps) */
     public static final String DEFAULT_SERVLET_ROOT = "0";
 
+    /** The default cache size for the script resolution. */
+    public static final Integer DEFAULT_CACHE_SIZE = 200;
+
     private static final String REF_SERVLET = "Servlet";
 
     /** @scr.reference */
@@ -146,6 +159,8 @@
     // a request. This field is set on demand by getDefaultErrorServlet()
     private Servlet defaultErrorServlet;
 
+    private Map<ResourceCollector, Servlet> cache;
+
     // ---------- ServletResolver interface -----------------------------------
 
     /**
@@ -427,6 +442,11 @@
      */
     private Servlet getServlet(final ResourceCollector locationUtil,
             final SlingHttpServletRequest request) {
+        final Servlet scriptServlet = (this.cache != null ? 
this.cache.get(locationUtil) : null);
+        if ( scriptServlet != null ) {
+            return scriptServlet;
+        }
+
         final Collection<Resource> candidates = 
locationUtil.getServlets(this.scriptResolver);
 
        if (log.isDebugEnabled()) {
@@ -440,6 +460,7 @@
                }
        }
 
+       boolean hasOptingServlet = false;
         for (Resource candidateResource : candidates) {
                if(log.isDebugEnabled()) {
                        log.debug("Checking if candidate resource {} adapts to 
servlet and accepts request",
@@ -451,8 +472,14 @@
                 boolean servletAcceptsRequest = !isOptingServlet
                     || ((OptingServlet) candidate).accepts(request);
                 if (servletAcceptsRequest) {
+                    if ( !hasOptingServlet && !isOptingServlet && this.cache 
!= null ) {
+                        this.cache.put(locationUtil, candidate);
+                    }
                     return candidate;
                 }
+                if ( isOptingServlet ) {
+                    hasOptingServlet = true;
+                }
                if(log.isDebugEnabled()) {
                        log.debug("Candidate {} does not accept request, 
ignored", candidateResource.getPath());
                }
@@ -579,6 +606,11 @@
 
         }
 
+        // create cache - if a cache size is configured
+        final int cacheSize = 
OsgiUtil.toInteger(properties.get(PROP_CACHE_SIZE), DEFAULT_CACHE_SIZE);
+        if ( cacheSize > 5 ) {
+            this.cache = new ConcurrentHashMap<ResourceCollector, 
Servlet>(cacheSize);
+        }
         createAllServlets(refs);
     }
 
@@ -597,6 +629,7 @@
             this.scriptSession = null;
         }
         this.context = null;
+        this.cache = null;
         this.servletResourceProviderFactory = null;
     }
 
@@ -717,4 +750,27 @@
             }
         }
     }
+
+    /**
+     * @see 
org.osgi.service.event.EventHandler#handleEvent(org.osgi.service.event.Event)
+     */
+    public void handleEvent(Event event) {
+        if ( this.cache != null ) {
+            // if the path of the event is a sub path of a search path
+            // we flush the whole cache
+            boolean flushCache = false;
+            final String path = (String) 
event.getProperty(SlingConstants.PROPERTY_PATH);
+            final String[] searchPaths = this.scriptResolver.getSearchPath();
+            int index = 0;
+            while ( !flushCache && index < searchPaths.length ) {
+                if ( path.startsWith(searchPaths[index]) ) {
+                    flushCache = true;
+                }
+                index++;
+            }
+            if ( flushCache ) {
+                this.cache.clear();
+            }
+        }
+    }
 }

Modified: 
sling/trunk/bundles/servlets/resolver/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: 
http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=789698&r1=789697&r2=789698&view=diff
==============================================================================
--- 
sling/trunk/bundles/servlets/resolver/src/main/resources/OSGI-INF/metatype/metatype.properties
 (original)
+++ 
sling/trunk/bundles/servlets/resolver/src/main/resources/OSGI-INF/metatype/metatype.properties
 Tue Jun 30 12:53:14 2009
@@ -21,7 +21,7 @@
 #
 # This file contains localization strings for configuration labels and
 # descriptions as used in the metatype.xml descriptor generated by the
-# the Sling SCR plugin
+# the Maven SCR plugin
 
 servletresolver.name = Apache Sling Servlet/Script Resolver and Error Handler
 servletresolver.description = The Sling Servlet and Script Resolver has \
@@ -43,4 +43,8 @@
 servletresolver.scriptUser.description = This optional property can specify \
  the repository user who is used to read the scripts. If none is specified \
  the admin user is used by default.
+
+servletresolver.cacheSize.name = Cache Size
+servletresolver.cacheSize.description = This property configures the size of 
the \
+ cache used for script resolution. A value lower than 5 disables the cache.
  
\ No newline at end of file


Reply via email to