This is an automated email from the ASF dual-hosted git repository.

radu pushed a commit to branch resource-type-execution
in repository 
https://gitbox.apache.org/repos/asf/sling-org-apache-sling-engine.git


The following commit(s) were added to refs/heads/resource-type-execution by 
this push:
     new 014da2a  refactoring
014da2a is described below

commit 014da2a9e3642ef0c0a445c8f780668ddde33be0
Author: Radu Cotescu <[email protected]>
AuthorDate: Fri Oct 5 16:10:47 2018 +0200

    refactoring
    
    * made cache entries reflect the number of protected resource type
    * optimised cache queries
---
 pom.xml                                            |  1 +
 .../permissions/ResourceTypeExecutionCache.java    | 45 ++++++++++++---
 .../ResourceTypePermissionEvaluator.java           | 64 +++++++++++++++-------
 3 files changed, 84 insertions(+), 26 deletions(-)

diff --git a/pom.xml b/pom.xml
index 521b55f..2ab24de 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,6 +46,7 @@
     <properties>
         <site.jira.version.id>12314287</site.jira.version.id>
         <site.javadoc.exclude>**.impl.**</site.javadoc.exclude>
+        <sling.java.version>8</sling.java.version>
     </properties>
 
     <build>
diff --git 
a/src/main/java/org/apache/sling/engine/impl/request/permissions/ResourceTypeExecutionCache.java
 
b/src/main/java/org/apache/sling/engine/impl/request/permissions/ResourceTypeExecutionCache.java
index 4aa6472..290c8ee 100644
--- 
a/src/main/java/org/apache/sling/engine/impl/request/permissions/ResourceTypeExecutionCache.java
+++ 
b/src/main/java/org/apache/sling/engine/impl/request/permissions/ResourceTypeExecutionCache.java
@@ -18,9 +18,12 @@
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.engine.impl.request.permissions;
 
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
@@ -37,24 +40,47 @@ import org.osgi.service.component.annotations.Component;
 )
 public class ResourceTypeExecutionCache implements ResourceChangeListener, 
ExternalResourceChangeListener {
 
-    private Map<String, Boolean> preEvaluatedPermissions = new 
CachingMap(65536);
+    private Map<String, CacheEntry> preEvaluatedPermissions = new 
CachingMap(65536);
     private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
     private final Lock readLock = rwl.readLock();
     private final Lock writeLock = rwl.writeLock();
+    private static final Set<String> EMPTY = Collections.emptySet();
 
-    public Boolean getCachedPermission(String key) {
+    Set<String> getAllowedUsers(String permission) {
         readLock.lock();
         try {
-            return preEvaluatedPermissions.get(key);
+            CacheEntry entry = preEvaluatedPermissions.get(permission);
+            if (entry != null) {
+                return entry.allowedUsers;
+            }
+            return EMPTY;
         } finally {
             readLock.unlock();
         }
     }
 
-    public void setCachedPermission(String key, Boolean value) {
+    Set<String> getDisallowedUsers(String permission) {
+        readLock.lock();
+        try {
+            CacheEntry entry = preEvaluatedPermissions.get(permission);
+            if (entry != null) {
+                return entry.disallowedUsers;
+            }
+            return EMPTY;
+        } finally {
+            readLock.unlock();
+        }
+    }
+
+    void updateResourceType(String permission, String user, boolean allow) {
         writeLock.lock();
         try {
-            preEvaluatedPermissions.put(key, value);
+            CacheEntry entry = 
preEvaluatedPermissions.computeIfAbsent(permission, k -> new CacheEntry());
+            if (allow) {
+                entry.allowedUsers.add(user);
+            } else {
+                entry.disallowedUsers.add(user);
+            }
         } finally {
             writeLock.unlock();
         }
@@ -70,7 +96,7 @@ public class ResourceTypeExecutionCache implements 
ResourceChangeListener, Exter
         }
     }
 
-    private class CachingMap extends LinkedHashMap<String, Boolean> {
+    private class CachingMap extends LinkedHashMap<String, CacheEntry> {
 
         private final int capacity;
 
@@ -79,8 +105,13 @@ public class ResourceTypeExecutionCache implements 
ResourceChangeListener, Exter
         }
 
         @Override
-        protected boolean removeEldestEntry(Map.Entry<String, Boolean> eldest) 
{
+        protected boolean removeEldestEntry(Map.Entry<String, CacheEntry> 
eldest) {
             return size() > capacity;
         }
     }
+
+    private class CacheEntry {
+        private Set<String> allowedUsers = new HashSet<>();
+        private Set<String> disallowedUsers = new HashSet<>();
+    }
 }
diff --git 
a/src/main/java/org/apache/sling/engine/impl/request/permissions/ResourceTypePermissionEvaluator.java
 
b/src/main/java/org/apache/sling/engine/impl/request/permissions/ResourceTypePermissionEvaluator.java
index 9b33783..9a66fa9 100644
--- 
a/src/main/java/org/apache/sling/engine/impl/request/permissions/ResourceTypePermissionEvaluator.java
+++ 
b/src/main/java/org/apache/sling/engine/impl/request/permissions/ResourceTypePermissionEvaluator.java
@@ -18,6 +18,8 @@
  
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
 package org.apache.sling.engine.impl.request.permissions;
 
+import java.util.Set;
+
 import org.apache.sling.api.SlingHttpServletRequest;
 import org.apache.sling.api.request.SlingRequestEvent;
 import org.apache.sling.api.request.SlingRequestListener;
@@ -55,32 +57,56 @@ public class ResourceTypePermissionEvaluator implements 
SlingRequestListener {
             final String userId = request.getResourceResolver().getUserID();
             if (userId != null) {
                 String permissionPath = resourceType.startsWith("/") ? 
RESOURCE_TYPE_PERMISSIONS + resourceType :
-                        RESOURCE_TYPE_PERMISSIONS + "/" + resourceType + 
"/http." + request.getMethod();
-                while (!RESOURCE_TYPE_PERMISSIONS.equals(permissionPath)) {
-                    String cacheKey = userId + ":" + permissionPath;
-                    Boolean cached = 
resourceTypeExecutionCache.getCachedPermission(cacheKey);
-                    if (cached != null) {
-                        return cached;
+                        RESOURCE_TYPE_PERMISSIONS + "/" + resourceType;
+                String permissionPathWithHttpMethod = permissionPath + 
"/http." + request.getMethod();
+                while (permissionPath != null && 
!RESOURCE_TYPE_PERMISSIONS.equals(permissionPath)) {
+
+                    Set<String> allowedUsers = 
resourceTypeExecutionCache.getAllowedUsers(permissionPathWithHttpMethod);
+                    if (allowedUsers.contains(userId)) {
+                        return true;
+                    }
+                    allowedUsers = 
resourceTypeExecutionCache.getAllowedUsers(permissionPath);
+                    if (allowedUsers.contains(userId)) {
+                        return true;
+                    }
+
+                    Set<String> disallowedUsers = 
resourceTypeExecutionCache.getDisallowedUsers(permissionPathWithHttpMethod);
+                    if (disallowedUsers.contains(userId)) {
+                        return false;
+                    }
+                    disallowedUsers = 
resourceTypeExecutionCache.getDisallowedUsers(permissionPath);
+                    if (disallowedUsers.contains(userId)) {
+                        return false;
                     }
-                    Resource permission = 
accessedResource.getResourceResolver().getResource(permissionPath);
+
+                    Resource permission = 
accessedResource.getResourceResolver().getResource(permissionPathWithHttpMethod);
+                    if (permission != null) {
+                        
resourceTypeExecutionCache.updateResourceType(permissionPathWithHttpMethod, 
userId, true);
+                        return true;
+                    }
+
+                    permission = 
accessedResource.getResourceResolver().getResource(permissionPath);
                     if (permission != null) {
-                        
resourceTypeExecutionCache.setCachedPermission(cacheKey, true);
+                        
resourceTypeExecutionCache.updateResourceType(permissionPath, userId, true);
                         return true;
-                    } else {
-                        ResourceResolver elevatedResourceResolver = 
threadLocalResourceResolver.get();
-                        if (elevatedResourceResolver != null) {
-                            permission = 
elevatedResourceResolver.getResource(permissionPath);
-                            if (permission != null) {
-                                
resourceTypeExecutionCache.setCachedPermission(cacheKey, false);
-                                return false;
-                            }
+                    }
+
+                    ResourceResolver elevatedResourceResolver = 
threadLocalResourceResolver.get();
+                    if (elevatedResourceResolver != null) {
+                        permission = 
elevatedResourceResolver.getResource(permissionPathWithHttpMethod);
+                        if (permission != null) {
+                            
resourceTypeExecutionCache.updateResourceType(permissionPathWithHttpMethod, 
userId, false);
+                            return false;
+                        }
+                        permission = 
elevatedResourceResolver.getResource(permissionPath);
+                        if (permission != null) {
+                            
resourceTypeExecutionCache.updateResourceType(permissionPath, userId, false);
+                            return false;
                         }
                     }
                     permissionPath = ResourceUtil.getParent(permissionPath);
                 }
-                resourceTypeExecutionCache.setCachedPermission(userId + ":" + 
(resourceType.startsWith("/") ?
-                        RESOURCE_TYPE_PERMISSIONS + resourceType :
-                        RESOURCE_TYPE_PERMISSIONS + "/" + resourceType + 
"/http." + request.getMethod()), true);
+                
resourceTypeExecutionCache.updateResourceType(permissionPathWithHttpMethod, 
userId, true);
                 return true;
             }
         }

Reply via email to