You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2015/12/31 11:36:07 UTC

svn commit: r1722435 - in /sling/trunk/contrib/extensions/acldef: it/src/main/provisioning/ it/src/test/java/org/apache/sling/acldef/it/ oak-jcr/src/main/java/org/apache/sling/acldef/jcr/impl/

Author: bdelacretaz
Date: Thu Dec 31 10:36:07 2015
New Revision: 1722435

URL: http://svn.apache.org/viewvc?rev=1722435&view=rev
Log:
SLING-5355 - test ACL definitions in provisioning model

Added:
    sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ProvisionedAclIT.java
      - copied, changed from r1722431, sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ImmediateAclIT.java
    sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/Retry.java
    sling/trunk/contrib/extensions/acldef/oak-jcr/src/main/java/org/apache/sling/acldef/jcr/impl/AclSetup.java
Removed:
    sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ImmediateAclIT.java
    sling/trunk/contrib/extensions/acldef/oak-jcr/src/main/java/org/apache/sling/acldef/jcr/impl/AclSetupComponent.java
Modified:
    sling/trunk/contrib/extensions/acldef/it/src/main/provisioning/model.txt

Modified: sling/trunk/contrib/extensions/acldef/it/src/main/provisioning/model.txt
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/acldef/it/src/main/provisioning/model.txt?rev=1722435&r1=1722434&r2=1722435&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/acldef/it/src/main/provisioning/model.txt (original)
+++ sling/trunk/contrib/extensions/acldef/it/src/main/provisioning/model.txt Thu Dec 31 10:36:07 2015
@@ -26,7 +26,23 @@
   org.apache.sling/org.apache.sling.acldef.oak-jcr/0.0.1-SNAPSHOT
   org.apache.sling/org.apache.sling.acldef.parser/0.0.1-SNAPSHOT
 
-[configurations]
-
 [settings]
   org.apache.sling.commons.log.julenabled=true
+
+[configurations]
+org.apache.sling.acldef.jcr.AclSetup-one
+  #
+  acldef.text.1="create service user fredWilma"
+  #
+  # multiline acldef statement
+  acldef.text.2="
+      set ACL for fredWilma
+        allow jcr:read on /var
+        deny jcr:write on /var
+      end"
+  #    
+  # single line with backslash n should work as well    
+  acldef.text.backs="set ACL for fredWilma \n deny jcr:write on /var \n end"
+  #
+  # this user will be created from code, to validate the async ACL setting    
+  acldef.text.another="set ACL for anotherUser \n deny jcr:write on /tmp \n end"
\ No newline at end of file

Copied: sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ProvisionedAclIT.java (from r1722431, sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ImmediateAclIT.java)
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ProvisionedAclIT.java?p2=sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ProvisionedAclIT.java&p1=sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ImmediateAclIT.java&r1=1722431&r2=1722435&rev=1722435&view=diff
==============================================================================
--- sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ImmediateAclIT.java (original)
+++ sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/ProvisionedAclIT.java Thu Dec 31 10:36:07 2015
@@ -16,12 +16,7 @@
  */
 package org.apache.sling.acldef.it;
 
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.util.Dictionary;
-import java.util.Hashtable;
-import java.util.UUID;
+import static org.junit.Assert.assertTrue;
 
 import javax.jcr.LoginException;
 import javax.jcr.RepositoryException;
@@ -31,20 +26,18 @@ import org.apache.jackrabbit.api.Jackrab
 import org.apache.jackrabbit.api.security.user.Authorizable;
 import org.apache.sling.jcr.api.SlingRepository;
 import org.apache.sling.junit.rules.TeleporterRule;
-import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
 
-public class ImmediateAclIT {
+/** Test service users and ACLs set from
+ *  our provisioning model. 
+ *  TODO test /var ACLs and use @Retry rule
+ */
+public class ProvisionedAclIT {
     
     @Rule
     public TeleporterRule teleporter = TeleporterRule.forClass(getClass(), "IT");
     
-    private final static String FACTORY_PID = "org.apache.sling.acldef.jcr.AclSetupComponent";
-    private final static String ACLDEF_PROP_PREFIX = "acldef.text.";
-
     private boolean userExists(String id) throws LoginException, RepositoryException, InterruptedException {
         final Session s = teleporter.getService(SlingRepository.class).loginAdministrative(null);
         
@@ -59,31 +52,15 @@ public class ImmediateAclIT {
         return false;
     }
     
-    @Before
-    public void waitForServices() {
-        WaitFor.services(teleporter, ConfigurationAdmin.class, SlingRepository.class);
-    }
-    
     @Test
-    public void createServiceUser() throws IOException, InterruptedException, LoginException, RepositoryException {
-        // Create a config for the AclSetupComponent and verify that the
-        // service user eventually gets created 
-        final String id = "user_" + UUID.randomUUID().toString();
-        final ConfigurationAdmin ca = teleporter.getService(ConfigurationAdmin.class);
-        final Configuration cfg = ca.createFactoryConfiguration(FACTORY_PID);
-        final Dictionary<String, Object> props = new Hashtable<String, Object>();
-        props.put(ACLDEF_PROP_PREFIX + "1", "create service user " + id);
-        cfg.setBundleLocation(null);
-        cfg.update(props);
-        
-        final long maxTimeMsec = 10000;
-        final long timeout = System.currentTimeMillis() + maxTimeMsec;
-        while(System.currentTimeMillis() < timeout) {
-            if(userExists(id)) {
-                return;
+    public void serviceUserCreated() throws Exception {
+        final String id = "fredWilma";
+        new Retry() {
+            @Override
+            public Void call() throws Exception {
+                assertTrue("Expecting user " + id, userExists(id));
+                return null;
             }
-            Thread.sleep(100L);
-        }
-        fail("User " + id + " was not created after " + maxTimeMsec + " msec");
+        };
     }
 }
\ No newline at end of file

Added: sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/Retry.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/Retry.java?rev=1722435&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/Retry.java (added)
+++ sling/trunk/contrib/extensions/acldef/it/src/test/java/org/apache/sling/acldef/it/Retry.java Thu Dec 31 10:36:07 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
+ *
+ *      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.acldef.it;
+
+import static org.junit.Assert.fail;
+import java.util.concurrent.Callable;
+
+/** RetryRule does not seem to work for teleported tests */
+public abstract class Retry implements Callable<Void> {
+    public static final int DEFAULT_INTERVAL = 100;
+    public static final int DEFAULT_TIMEOUT = 10000;
+    
+    public Retry() throws Exception {
+        this(DEFAULT_TIMEOUT, DEFAULT_INTERVAL);
+    }
+    
+    public Retry(int timeout, int interval) {
+        final long endTime = System.currentTimeMillis() + timeout;
+        Throwable failure = null;
+        while(System.currentTimeMillis() < endTime) {
+            try {
+                failure = null;
+                call();
+                break;
+            } catch(Throwable t) {
+                failure = t;
+                try {
+                    Thread.sleep(interval);
+                } catch(InterruptedException ignore) {
+                }
+            }
+        }
+        if(failure != null) {
+            if(failure instanceof AssertionError) {
+                throw (AssertionError)failure;
+            }
+            fail("Failed with timeout:" + failure.toString());
+        }
+    }
+}
\ No newline at end of file

Added: sling/trunk/contrib/extensions/acldef/oak-jcr/src/main/java/org/apache/sling/acldef/jcr/impl/AclSetup.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/acldef/oak-jcr/src/main/java/org/apache/sling/acldef/jcr/impl/AclSetup.java?rev=1722435&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/acldef/oak-jcr/src/main/java/org/apache/sling/acldef/jcr/impl/AclSetup.java (added)
+++ sling/trunk/contrib/extensions/acldef/oak-jcr/src/main/java/org/apache/sling/acldef/jcr/impl/AclSetup.java Thu Dec 31 10:36:07 2015
@@ -0,0 +1,154 @@
+/*
+ * 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.acldef.jcr.impl;
+
+import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import javax.jcr.Session;
+
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.sling.acldef.jcr.AclOperationVisitor;
+import org.apache.sling.acldef.parser.AclDefinitionsParser;
+import org.apache.sling.acldef.parser.operations.Operation;
+import org.apache.sling.commons.threads.ThreadPool;
+import org.apache.sling.commons.threads.ThreadPoolManager;
+import org.apache.sling.jcr.api.SlingRepository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import aQute.bnd.annotation.component.Deactivate;
+
+/** OSGi component that sets up service users and ACLS
+ *  based on configurations created by the acldef provisioning
+ *  model processor.
+ *  
+ *  As Oak requires a path to exist before setting an ACL on it,
+ *  this component needs to retry setting ACLs when that fails
+ *  due to a non-existing path.
+ */
+@Component(
+        configurationFactory=true,
+        metatype=false,
+        configurationPid=AclSetup.CONFIG_PID,
+        policy=ConfigurationPolicy.REQUIRE)
+public class AclSetup implements Runnable {
+    private final Logger log = LoggerFactory.getLogger(getClass());
+    public static final String CONFIG_PID = "org.apache.sling.acldef.jcr.AclSetup";
+    public static final String ACLDEF_PROP_PREFIX = "acldef.text.";
+    public static final String THREAD_POOL_NAME = "ACL Definitions";
+    
+    private List<String> todo; 
+    private ThreadPool threadPool;
+    private boolean running;
+    
+    @Reference
+    AclDefinitionsParser parser;
+    
+    @Reference
+    ThreadPoolManager threadPoolManager;
+    
+    @Reference
+    SlingRepository repository;
+    
+    @Activate
+    public void activate(Map<String, Object> config) {
+        todo  = new ArrayList<String>();
+        threadPool = threadPoolManager.get(THREAD_POOL_NAME);
+        
+        for(String key : config.keySet()) {
+            if(key.startsWith(ACLDEF_PROP_PREFIX)) {
+                final String value = (String)config.get(key);
+                todo.add(value);
+            }
+        }
+        if(todo.isEmpty()) {
+            log.error("No {} properties in configuration {}, nothing to do", ACLDEF_PROP_PREFIX, config);
+        } else {
+            log.info("Got {} ACL definitions to execute asynchronously", todo.size());
+            running = true;
+            threadPool.execute(this);
+        }
+    }
+    
+    @Deactivate
+    public void deactivate(Map<String, Object> config) {
+        synchronized (this) {
+            running = false;
+            threadPoolManager.release(threadPool);
+        }
+    }
+
+    private void sleep(int msec) {
+        try {
+            Thread.sleep(msec);
+        } catch(InterruptedException ignore) {
+        }
+    }
+    
+    @Override
+    public void run() {
+        log.info("Applying {} ACL definition snippets", todo.size());
+
+        List<String> newTodo = new ArrayList<String>();
+        Session s = null;
+        try {
+            s = repository.loginAdministrative(null);
+            final AclOperationVisitor visitor = new AclOperationVisitor(s);
+            for(String acldef : todo) {
+                try {
+                    for(Operation op : parser.parse(new StringReader(acldef))) {
+                        op.accept(visitor);
+                        s.save();
+                    }
+                } catch(Exception e) {
+                    log.warn("Exception while executing an ACL definition:" + e.toString(), e);
+                    newTodo.add(acldef);
+                }
+            }
+        } catch(Exception e) {
+            log.warn("Exception while executing ACL definitions, will retry everything:" + e.toString(), e);
+            newTodo = todo;
+        } finally {
+            if(s != null) {
+                s.logout();
+            }
+        }
+        
+        // TODO schedule with exponential backoff?
+        if(!newTodo.isEmpty() && running) {
+            sleep(1000);
+        }
+        
+        synchronized (this) {
+            todo = newTodo;
+            if(todo.isEmpty()) {
+                log.info("All ACL definitions executed");
+            } else if(running) {
+                log.info("{} ACL definitions left to execute, will retry", todo.size());
+                threadPool.execute(this);
+            } else {
+                log.info("Some operations failed but not running anymore");
+            }
+        }
+    }
+}
\ No newline at end of file