You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2014/03/24 09:30:04 UTC

svn commit: r1580784 - in /sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal: ScriptResource.java SlingServletResolver.java

Author: cziegeler
Date: Mon Mar 24 08:30:03 2014
New Revision: 1580784

URL: http://svn.apache.org/r1580784
Log:
SLING-3441 : Avoid shared resource resolver usage

Added:
    sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ScriptResource.java   (with props)
Modified:
    sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/SlingServletResolver.java

Added: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ScriptResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ScriptResource.java?rev=1580784&view=auto
==============================================================================
--- sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ScriptResource.java (added)
+++ sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ScriptResource.java Mon Mar 24 08:30:03 2014
@@ -0,0 +1,163 @@
+/*
+ * 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.servlets.resolver.internal;
+
+import java.lang.ref.WeakReference;
+import java.util.Iterator;
+
+import javax.servlet.Servlet;
+
+import org.apache.sling.api.resource.AbstractResource;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceMetadata;
+import org.apache.sling.api.resource.ResourceResolver;
+
+/**
+ * ScriptResource is a resource wrapper of a resource fetched by a
+ * per thread resource resolver.
+ * As the script engines usually keep a reference to this resource
+ * for a longer time, the resource switches internally to
+ * a resource fetched by the shared resource resolver.
+ *
+ * We can't extend ResourceWrapper as its not possible to clear
+ * the wrapped resource field.
+ */
+public class ScriptResource extends AbstractResource {
+
+    private Resource activeResource;
+
+    private final ResourceResolver sharedResourceResolver;
+
+    private WeakReference<ResourceResolver> perThreadResourceResolver;
+
+    public ScriptResource(final Resource resource, final ResourceResolver sharedResourceResolver) {
+        this.perThreadResourceResolver = new WeakReference<ResourceResolver>(resource.getResourceResolver());
+        this.sharedResourceResolver = sharedResourceResolver;
+        this.activeResource = resource;
+    }
+
+    private Resource getActiveResource() {
+        if ( this.perThreadResourceResolver != null ) {
+            final ResourceResolver rr = this.perThreadResourceResolver.get();
+            if ( rr == null || !rr.isLive() ) {
+                this.perThreadResourceResolver = null;
+                this.activeResource = this.sharedResourceResolver.getResource(this.activeResource.getPath());
+            }
+        }
+        return this.activeResource;
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.Resource#getResourceType()
+     */
+    public String getResourceType() {
+        return this.getActiveResource().getResourceType();
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.Resource#getResourceSuperType()
+     */
+    public String getResourceSuperType() {
+        return this.getActiveResource().getResourceSuperType();
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.Resource#getResourceResolver()
+     */
+    public ResourceResolver getResourceResolver() {
+        return this.getActiveResource().getResourceResolver();
+    }
+
+    /**
+     * @see org.apache.sling.api.adapter.SlingAdaptable#adaptTo(java.lang.Class)
+     */
+    @SuppressWarnings("unchecked")
+    @Override
+    public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) {
+        if ( type == Servlet.class ) {
+            final Servlet s = (Servlet)super.adaptTo(type);
+            if ( s != null ) {
+                return (AdapterType)s;
+            }
+        }
+        return this.getActiveResource().adaptTo(type);
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.Resource#getPath()
+     */
+    public String getPath() {
+        return this.getActiveResource().getPath();
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.Resource#getResourceMetadata()
+     */
+    public ResourceMetadata getResourceMetadata() {
+        return this.getActiveResource().getResourceMetadata();
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.AbstractResource#getName()
+     */
+    @Override
+    public String getName() {
+        return this.getActiveResource().getName();
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.AbstractResource#getParent()
+     */
+    @Override
+    public Resource getParent() {
+        return this.getActiveResource().getParent();
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.AbstractResource#getChild(java.lang.String)
+     */
+    @Override
+    public Resource getChild(String relPath) {
+        return this.getActiveResource().getChild(relPath);
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.AbstractResource#listChildren()
+     */
+    @Override
+    public Iterator<Resource> listChildren() {
+        return this.getActiveResource().listChildren();
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.AbstractResource#getChildren()
+     */
+    @Override
+    public Iterable<Resource> getChildren() {
+        return this.getActiveResource().getChildren();
+    }
+
+    /**
+     * @see org.apache.sling.api.resource.AbstractResource#isResourceType(java.lang.String)
+     */
+    @Override
+    public boolean isResourceType(String resourceType) {
+        return this.getActiveResource().isResourceType(resourceType);
+    }
+}

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ScriptResource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ScriptResource.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/servlets/resolver/src/main/java/org/apache/sling/servlets/resolver/internal/ScriptResource.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

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=1580784&r1=1580783&r2=1580784&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 Mon Mar 24 08:30:03 2014
@@ -235,7 +235,7 @@ public class SlingServletResolver
         Servlet servlet = null;
 
         if ( type != null && type.length() > 0 ) {
-            servlet = resolveServletInternal(request, type, scriptResolver);
+            servlet = resolveServletInternal(request, null, type, scriptResolver);
         }
 
         // last resort, use the core bundle default servlet
@@ -277,7 +277,7 @@ public class SlingServletResolver
         }
 
         final ResourceResolver scriptResolver = this.getScriptResourceResolver();
-        final Servlet servlet = resolveServletInternal(resource, scriptName, scriptResolver);
+        final Servlet servlet = resolveServletInternal(null, resource, scriptName, scriptResolver);
 
         // log the servlet found
         if (LOGGER.isDebugEnabled()) {
@@ -303,7 +303,7 @@ public class SlingServletResolver
         }
 
         final ResourceResolver scriptResolver = this.getScriptResourceResolver();
-        final Servlet servlet = resolveServletInternal((Resource)null, scriptName, scriptResolver);
+        final Servlet servlet = resolveServletInternal(null, (Resource)null, scriptName, scriptResolver);
 
         // log the servlet found
         if (LOGGER.isDebugEnabled()) {
@@ -317,40 +317,26 @@ public class SlingServletResolver
         return servlet;
     }
 
-    /** Internal method to resolve a servlet. */
-    private Servlet resolveServletInternal(
-            final Resource resource,
-            final String scriptName,
-            final ResourceResolver resolver) {
-        Servlet servlet = null;
-
-        // first check whether the type of a resource is the absolute
-        // path of a servlet (or script)
-        if (scriptName.charAt(0) == '/') {
-            final String scriptPath = ResourceUtil.normalize(scriptName);
-            if ( this.isPathAllowed(scriptPath) ) {
-                final Resource res = resolver.getResource(scriptPath);
-                if (res != null) {
-                    servlet = res.adaptTo(Servlet.class);
-                }
-                if (servlet != null && LOGGER.isDebugEnabled()) {
-                    LOGGER.debug("Servlet {} found using absolute resource type {}", RequestUtil.getServletName(servlet),
-                                    scriptName);
-                }
-            }
-        }
-        if ( servlet == null ) {
-            // the resource type is not absolute, so lets go for the deep search
-            final NamedScriptResourceCollector locationUtil = NamedScriptResourceCollector.create(scriptName, resource, this.executionPaths);
-            servlet = getServletInternal(locationUtil, null, resolver);
-
-            if (LOGGER.isDebugEnabled() && servlet != null) {
-                LOGGER.debug("resolveServlet returns servlet {}", RequestUtil.getServletName(servlet));
-            }
-        }
-        return servlet;
-
+    /**
+     * Get the servlet for the resource.
+     */
+    private Servlet getServlet(final Resource scriptResource) {
+        // no resource -> no servlet
+        if ( scriptResource == null ) {
+            return null;
+        }
+        // if resource is fetched using shared resource resolver
+        // or resource is a servlet resource, just adapt to servlet
+        if ( scriptResource.getResourceResolver() == this.sharedScriptResolver
+             || "sling/bundle/resource".equals(scriptResource.getResourceSuperType()) ) {
+            return scriptResource.adaptTo(Servlet.class);
+        }
+        // return a resource wrapper to make sure the implementation
+        // switches from the per thread resource resolver to the shared once
+        // the per thread resource resolver is closed
+        return new ScriptResource(scriptResource, this.sharedScriptResolver).adaptTo(Servlet.class);
     }
+
     // ---------- ScriptResolver interface ------------------------------------
 
     /**
@@ -366,7 +352,7 @@ public class SlingServletResolver
             final String path = ResourceUtil.normalize(name);
             if ( this.isPathAllowed(path) ) {
                 final Resource resource = resourceResolver.getResource(path);
-                if (resource != null) {
+                if ( resource != null ) {
                     script = resource.adaptTo(SlingScript.class);
                 }
             }
@@ -561,42 +547,48 @@ public class SlingServletResolver
         return res;
     }
 
-    /**
+     /**
      * Resolve an appropriate servlet for a given request and resource type
      * using the provided ResourceResolver
      */
     private Servlet resolveServletInternal(final SlingHttpServletRequest request,
-            final String type,
+            final Resource resource,
+            final String scriptName,
             final ResourceResolver resolver) {
         Servlet servlet = null;
 
         // first check whether the type of a resource is the absolute
         // path of a servlet (or script)
-        if (type.charAt(0) == '/') {
-            String scriptPath = ResourceUtil.normalize(type);
+        if (scriptName.charAt(0) == '/') {
+            final String scriptPath = ResourceUtil.normalize(scriptName);
             if ( this.isPathAllowed(scriptPath) ) {
                 final Resource res = resolver.getResource(scriptPath);
-                if (res != null) {
-                    servlet = res.adaptTo(Servlet.class);
-                }
+                servlet = this.getServlet(res);
                 if (servlet != null && LOGGER.isDebugEnabled()) {
                     LOGGER.debug("Servlet {} found using absolute resource type {}", RequestUtil.getServletName(servlet),
-                                    type);
+                                    scriptName);
                 }
             } else {
-                request.getRequestProgressTracker().log(
-                        "Will not look for a servlet at {0} as it is not in the list of allowed paths",
-                        type
-                        );
+                if ( request != null ) {
+                    request.getRequestProgressTracker().log(
+                            "Will not look for a servlet at {0} as it is not in the list of allowed paths",
+                            scriptName
+                            );
+                }
             }
         }
         if ( servlet == null ) {
             // the resource type is not absolute, so lets go for the deep search
-            final ResourceCollector locationUtil = ResourceCollector.create(request, this.executionPaths, this.defaultExtensions);
+            final AbstractResourceCollector locationUtil;
+            if ( request != null ) {
+                locationUtil = ResourceCollector.create(request, this.executionPaths, this.defaultExtensions);
+            } else {
+                locationUtil = NamedScriptResourceCollector.create(scriptName, resource, this.executionPaths);
+            }
             servlet = getServletInternal(locationUtil, request, resolver);
 
             if (servlet != null && LOGGER.isDebugEnabled()) {
-                LOGGER.debug("getServlet returns servlet {}", RequestUtil.getServletName(servlet));
+                LOGGER.debug("getServletInternal returns servlet {}", RequestUtil.getServletName(servlet));
             }
         }
         return servlet;
@@ -648,12 +640,10 @@ public class SlingServletResolver
         }
 
         boolean hasOptingServlet = false;
-        for (Resource candidateResource : candidates) {
-            if (LOGGER.isDebugEnabled()) {
-                LOGGER.debug("Checking if candidate resource {} adapts to servlet and accepts request", candidateResource
+        for (final Resource candidateResource : candidates) {
+            LOGGER.debug("Checking if candidate resource {} adapts to servlet and accepts request", candidateResource
                         .getPath());
-            }
-            Servlet candidate = candidateResource.adaptTo(Servlet.class);
+            Servlet candidate = this.getServlet(candidateResource);
             if (candidate != null) {
                 final boolean isOptingServlet = candidate instanceof OptingServlet;
                 boolean servletAcceptsRequest = !isOptingServlet || (request != null && ((OptingServlet) candidate).accepts(request));
@@ -673,13 +663,9 @@ public class SlingServletResolver
                 if (isOptingServlet) {
                     hasOptingServlet = true;
                 }
-                if (LOGGER.isDebugEnabled()) {
-                    LOGGER.debug("Candidate {} does not accept request, ignored", candidateResource.getPath());
-                }
+                LOGGER.debug("Candidate {} does not accept request, ignored", candidateResource.getPath());
             } else {
-                if (LOGGER.isDebugEnabled()) {
-                    LOGGER.debug("Candidate {} does not adapt to a servlet, ignored", candidateResource.getPath());
-                }
+                LOGGER.debug("Candidate {} does not adapt to a servlet, ignored", candidateResource.getPath());
             }
         }
 
@@ -696,9 +682,9 @@ public class SlingServletResolver
         if (defaultServlet == null) {
             try {
                 Servlet servlet = new DefaultServlet();
-                servlet.init(new SlingServletConfig(servletContext, null, "Sling Core Default Servlet"));
+                servlet.init(new SlingServletConfig(servletContext, null, "Apache Sling Core Default Servlet"));
                 defaultServlet = servlet;
-            } catch (ServletException se) {
+            } catch (final ServletException se) {
                 LOGGER.error("Failed to initialize default servlet", se);
             }
         }
@@ -851,6 +837,9 @@ public class SlingServletResolver
             this.cacheSize = 0;
         }
 
+        // setup default servlet
+        this.getDefaultServlet();
+
         // and finally register as event listener
         this.eventHandlerReg = context.getBundleContext().registerService(EventHandler.class.getName(), this,
                 properties);