jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r1646435 [1/3] - in /jackrabbit/trunk: jackrabbit-jcr-client/src/test/java/org/apache/jackrabbit/client/ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ jackrabbit-jcr-server/src/main/java/org/apache/jackrab...
Date Thu, 18 Dec 2014 10:43:32 GMT
Author: angela
Date: Thu Dec 18 10:43:31 2014
New Revision: 1646435

URL: http://svn.apache.org/r1646435
Log:
JCR-2113 : JSR 283 Access Control Management (patch provided by alfusainey jallow, commit with minor modifications and some TODOs (in particular testing).

Added:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/IgnoreOperation.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetTree.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/tree/
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/tree/AbstractTree.java
    jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Tree.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/BatchUtils.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/DocumentTree.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/JsonTree.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/Utils.java
    jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/XmlTree.java
Modified:
    jackrabbit/trunk/jackrabbit-jcr-client/src/test/java/org/apache/jackrabbit/client/RepositoryFactoryImplTest.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java
    jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/RepositoryStubImpl.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProvider.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProviderStub.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlManagerImpl.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlProviderImpl.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlListImplTest.java
    jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlManagerImplTest.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/AbstractRepositoryService.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/SerializableBatch.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ChangeLogImpl.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/ConsolidatingChangeLog.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/batch/Operations.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/BatchLogger.java
    jackrabbit/trunk/jackrabbit-spi-commons/src/main/java/org/apache/jackrabbit/spi/commons/logging/RepositoryServiceLogger.java
    jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/Batch.java
    jackrabbit/trunk/jackrabbit-spi/src/main/java/org/apache/jackrabbit/spi/RepositoryService.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2dav/RepositoryServiceImpl.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java
    jackrabbit/trunk/jackrabbit-spi2jcr/src/main/java/org/apache/jackrabbit/spi2jcr/RepositoryServiceImpl.java
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/CurrentUserPrivilegeSetProperty.java
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/security/SupportedPrivilegeSetProperty.java

Modified: jackrabbit/trunk/jackrabbit-jcr-client/src/test/java/org/apache/jackrabbit/client/RepositoryFactoryImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-client/src/test/java/org/apache/jackrabbit/client/RepositoryFactoryImplTest.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-client/src/test/java/org/apache/jackrabbit/client/RepositoryFactoryImplTest.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-client/src/test/java/org/apache/jackrabbit/client/RepositoryFactoryImplTest.java Thu Dec 18 10:43:31 2014
@@ -81,6 +81,7 @@ import org.apache.jackrabbit.spi.Reposit
 import org.apache.jackrabbit.spi.RepositoryServiceFactory;
 import org.apache.jackrabbit.spi.SessionInfo;
 import org.apache.jackrabbit.spi.Subscription;
+import org.apache.jackrabbit.spi.Tree;
 import org.apache.jackrabbit.spi.commons.logging.Slf4jLogWriterProvider;
 import org.apache.jackrabbit.webdav.DavException;
 
@@ -301,6 +302,11 @@ public class RepositoryFactoryImplTest e
         }
 
         @Override
+        public PrivilegeDefinition[] getPrivileges(SessionInfo sessionInfo, NodeId id) throws RepositoryException {
+            return new PrivilegeDefinition[0];
+        }
+
+        @Override
         public PrivilegeDefinition[] getSupportedPrivileges(SessionInfo sessionInfo, NodeId nodeId) throws RepositoryException {
             return new PrivilegeDefinition[0];
         }
@@ -341,6 +347,11 @@ public class RepositoryFactoryImplTest e
             // empty
         }
 
+        @Override
+        public Tree createTree(SessionInfo sessionInfo, Batch batch, Name nodeName, Name primaryTypeName, String uniqueId) throws RepositoryException {
+            return null;
+        }
+
         public void importXml(SessionInfo sessionInfo, NodeId parentId, InputStream xmlStream, int uuidBehaviour) throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException, AccessDeniedException, UnsupportedRepositoryOperationException, RepositoryException {
             // empty
         }

Added: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java?rev=1646435&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/AclRemoveHandler.java Thu Dec 18 10:43:31 2014
@@ -0,0 +1,61 @@
+/*
+ * 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.jackrabbit.server.remoting.davex;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+
+import org.apache.jackrabbit.util.Text;
+
+public class AclRemoveHandler implements ProtectedItemRemoveHandler {
+
+    private static final String NT_REP_ACL = "rep:ACL";
+
+    @Override
+    public boolean remove(Session session, String itemPath) throws RepositoryException {
+        if (canHandle(session, itemPath)) {
+            String controlledPath = Text.getRelativeParent(itemPath, 1);
+            AccessControlManager acMgr = session.getAccessControlManager();
+            AccessControlPolicy[] policies = acMgr.getPolicies(controlledPath);
+            for (AccessControlPolicy policy : policies) {
+                acMgr.removePolicy(controlledPath, policy);
+            }
+            return true;
+        }
+        return false;
+    }
+
+    // -----------------------------------------------------------< private >---
+    private boolean canHandle(Session session, String itemPath) throws RepositoryException {
+        Item aclItem = session.getItem(itemPath);
+        if (aclItem.isNode() && itemPath.startsWith("/")) {
+            if (isJackrabbitAclNodeType((Node) aclItem)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean isJackrabbitAclNodeType(Node aclNode) throws RepositoryException {
+        String ntName = aclNode.getPrimaryNodeType().getName();
+        return ntName.equals(NT_REP_ACL);
+    }
+}

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JcrRemotingServlet.java Thu Dec 18 10:43:31 2014
@@ -235,12 +235,18 @@ public abstract class JcrRemotingServlet
      */
     public static final String INIT_PARAM_BATCHREAD_CONFIG = "batchread-config";
 
+    /**
+     * the 'protectedhandlers-config' init paramter.
+     */
+    public static final String INIT_PARAM_PROTECTED_HANDLERS_CONFIG = "protectedhandlers-config";
+    
     private static final String PARAM_DIFF = ":diff";
     private static final String PARAM_COPY = ":copy";
     private static final String PARAM_CLONE = ":clone";
     private static final String PARAM_INCLUDE = ":include";
 
     private BatchReadConfig brConfig;
+    private ProtectedRemoveManager protectedRemoveManager;
 
     @Override
     public void init() throws ServletException {
@@ -264,6 +270,13 @@ public abstract class JcrRemotingServlet
             }
         }
 
+        String protectedHandlerConfig = getServletConfig().getInitParameter(INIT_PARAM_PROTECTED_HANDLERS_CONFIG);
+        try {
+            protectedRemoveManager = new ProtectedRemoveManager(protectedHandlerConfig);
+        } catch (IOException e) {
+            log.debug("Unable to create ProtectedRemoveManager from " + protectedHandlerConfig + ".");
+        }
+
         // Determine the configured location for temporary files used when
         // processing file uploads. Since JCR-3029 the default is the
         // standard java.io.tmpdir location, but the presence of explicit
@@ -395,13 +408,13 @@ public abstract class JcrRemotingServlet
                     loc = copy(session, pValues, davResource.getLocator());
                 } else if (data.getParameterValues(PARAM_DIFF) != null) {
                     String targetPath = davResource.getLocator().getRepositoryPath();
-                    processDiff(session, targetPath, data);
+                    processDiff(session, targetPath, data, protectedRemoveManager);
                 } else if ((pValues = data.getParameterValues(PARAM_INCLUDE)) != null
                         && canHandle(DavMethods.DAV_GET, webdavRequest, davResource)) {
                     includes = pValues;
                 } else {
                     String targetPath = davResource.getLocator().getRepositoryPath();
-                    loc = modifyContent(session, targetPath, data);
+                    loc = modifyContent(session, targetPath, data, protectedRemoveManager);
                 }
 
                 // TODO: append entity
@@ -510,11 +523,11 @@ public abstract class JcrRemotingServlet
         return null;
     }
 
-    private static void processDiff(Session session, String targetPath, RequestData data)
+    private static void processDiff(Session session, String targetPath, RequestData data, ProtectedRemoveManager protectedRemoveManager)
             throws RepositoryException, DiffException, IOException {
 
         String[] diffs = data.getParameterValues(PARAM_DIFF);
-        DiffHandler handler = new JsonDiffHandler(session, targetPath, data);
+        DiffHandler handler = new JsonDiffHandler(session, targetPath, data, protectedRemoveManager);
         DiffParser parser = new DiffParser(handler);
 
         for (String diff : diffs) {
@@ -542,10 +555,10 @@ public abstract class JcrRemotingServlet
      * @throws RepositoryException
      * @throws DiffException
      */
-    private static String modifyContent(Session session, String targetPath, RequestData data)
+    private static String modifyContent(Session session, String targetPath, RequestData data, ProtectedRemoveManager protectedRemoveManager)
             throws RepositoryException, DiffException {
 
-        JsonDiffHandler dh = new JsonDiffHandler(session, targetPath, data);
+        JsonDiffHandler dh = new JsonDiffHandler(session, targetPath, data, protectedRemoveManager);
         boolean success = false;
         try {
             for (Iterator<String> pNames = data.getParameterNames(); pNames.hasNext();) {

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/JsonDiffHandler.java Thu Dec 18 10:43:31 2014
@@ -34,12 +34,15 @@ import javax.jcr.Item;
 import javax.jcr.ItemNotFoundException;
 import javax.jcr.Node;
 import javax.jcr.NodeIterator;
+import javax.jcr.Property;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.ItemDefinition;
 import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.NodeTypeManager;
@@ -65,14 +68,20 @@ class JsonDiffHandler implements DiffHan
     private final ValueFactory vf;
     private final String requestItemPath;
     private final RequestData data;
+    private final ProtectedRemoveManager protectedRemoveManager;
 
     private NodeTypeManager ntManager;
 
     JsonDiffHandler(Session session, String requestItemPath, RequestData data) throws RepositoryException {
+        this(session, requestItemPath, data, null);
+    }
+
+    JsonDiffHandler(Session session, String requestItemPath, RequestData data, ProtectedRemoveManager protectedRemoveManager) throws RepositoryException {
         this.session = session;
         this.requestItemPath = requestItemPath;
         this.data = data;
         vf = session.getValueFactory();
+        this.protectedRemoveManager = protectedRemoveManager;
     }
 
     //--------------------------------------------------------< DiffHandler >---
@@ -172,7 +181,17 @@ class JsonDiffHandler implements DiffHan
         }
         try {
             String itemPath = getItemPath(targetPath);
-            session.getItem(itemPath).remove();
+            Item item = session.getItem(itemPath);
+            
+            ItemDefinition def = (item.isNode()) ? ((Node) item).getDefinition() : ((Property) item).getDefinition();
+            if (def.isProtected()) {
+                // delegate to the manager.
+                if (protectedRemoveManager == null || !protectedRemoveManager.remove(session, itemPath)) {
+                   throw new ConstraintViolationException("Cannot remove protected node: no suitable handler configured.");
+                }
+            } else {
+                item.remove();
+            }
         } catch (RepositoryException e) {
             throw new DiffException(e.getMessage(), e);
         }

Added: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java?rev=1646435&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedItemRemoveHandler.java Thu Dec 18 10:43:31 2014
@@ -0,0 +1,28 @@
+/*
+ * 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.jackrabbit.server.remoting.davex;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+/**
+ * ProtectedItemRemoveHandler... TODO
+ */
+public interface ProtectedItemRemoveHandler {
+
+    public boolean remove(Session session, String itemPath) throws RepositoryException;
+}

Added: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java?rev=1646435&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/ProtectedRemoveManager.java Thu Dec 18 10:43:31 2014
@@ -0,0 +1,97 @@
+/*
+ * 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.jackrabbit.server.remoting.davex;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Properties;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ProtectedRemoveManager {
+
+    private static final Logger log = LoggerFactory.getLogger(ProtectedRemoveManager.class);
+
+    private List<ProtectedItemRemoveHandler> handlers = new ArrayList<ProtectedItemRemoveHandler>();
+
+    public ProtectedRemoveManager(String config) throws IOException {
+        Properties props = new Properties();
+        if (config == null) {
+            log.warn("protectedhandlers-config is missing -> DIFF processing can fail for the Remove operation if the content to" +
+                    "remove is protected!");
+        } else {
+            File file = new File(config);
+            if (file.exists()) {
+                InputStream inStream = new FileInputStream(file);
+                props.load(inStream);
+                for (Enumeration<?> en = props.propertyNames(); en.hasMoreElements();) {
+                    String key = en.nextElement().toString();
+                    String className = props.getProperty(key);
+                    if (!className.isEmpty()) {
+                        ProtectedItemRemoveHandler irHandler = createHandler(className);
+                        if (irHandler != null) {
+                            handlers.add(irHandler);
+                        }
+                    }
+                }
+            } else {
+                log.debug("Fail to locate the protected-item-remove-handler properties file.");
+            }
+        }
+    }
+
+    public boolean remove(Session session, String itemPath) throws RepositoryException {
+        for (ProtectedItemRemoveHandler handler : handlers) {
+            if (handler.remove(session, itemPath)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Instantiates and returns a concrete ProtectedItemRemoveHandler implementation.
+     * @param className
+     * @return
+     * @throws RepositoryException
+     */
+    private static ProtectedItemRemoveHandler createHandler(String className) {
+        try {
+            Class<?> irHandlerClass = Class.forName(className);
+            if (ProtectedItemRemoveHandler.class.isAssignableFrom(irHandlerClass)) {
+                ProtectedItemRemoveHandler irHandler = (ProtectedItemRemoveHandler) irHandlerClass.newInstance();
+                return irHandler;
+            }
+        } catch (ClassNotFoundException e) {
+            log.error(e.getMessage(), e);
+        } catch (InstantiationException e) {
+            log.error(e.getMessage(), e);
+        } catch (IllegalAccessException e) {
+            log.error(e.getMessage(), e);
+        }
+        return null;
+    }
+}

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesProperty.java Thu Dec 18 10:43:31 2014
@@ -52,7 +52,7 @@ public class JcrUserPrivilegesProperty {
 
             String prefix = Text.getNamespacePrefix(privilegeName);
             Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, session.getNamespaceURI(prefix));
-            davPrivs.add(Privilege.getPrivilege(privilegeName, ns));
+            davPrivs.add(Privilege.getPrivilege(Text.getLocalName(privilegeName), ns));
         }
 
         return new CurrentUserPrivilegeSetProperty(davPrivs.toArray(new Privilege[davPrivs.size()]));

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/test/java/org/apache/jackrabbit/webdav/jcr/security/JcrUserPrivilegesPropertyTest.java Thu Dec 18 10:43:31 2014
@@ -32,9 +32,10 @@ public class JcrUserPrivilegesPropertyTe
     private Set<Privilege> getExpected(AccessControlManager acMgr, Session s) throws RepositoryException {
         Set<Privilege> expected = new HashSet<Privilege>();
         for (javax.jcr.security.Privilege p : acMgr.getPrivileges(testRoot)) {
+            String localName = Text.getLocalName(p.getName());
             String prefix = Text.getNamespacePrefix(p.getName());
             Namespace ns = (prefix.isEmpty()) ? Namespace.EMPTY_NAMESPACE : Namespace.getNamespace(prefix, s.getNamespaceURI(prefix));
-            expected.add(Privilege.getPrivilege(p.getName(), ns));
+            expected.add(Privilege.getPrivilege(localName, ns));
         }
         return expected;
     }

Added: jackrabbit/trunk/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties?rev=1646435&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties (added)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/test/resources/protectedHandlers.properties Thu Dec 18 10:43:31 2014
@@ -0,0 +1,17 @@
+#  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.
+
+# ProtectedItemRemoveHandler implementation class
+javax.jcr.tck.access.control.list.handler=org.apache.jackrabbit.server.remoting.davex.AclRemoveHandler

Modified: jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/RepositoryStubImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/RepositoryStubImpl.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/RepositoryStubImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2dav/src/test/java/org/apache/jackrabbit/jcr2dav/RepositoryStubImpl.java Thu Dec 18 10:43:31 2014
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.jcr2dav;
 
+import java.util.HashMap;
+import java.util.Map;
 import java.util.Properties;
 
 import javax.jcr.Repository;
@@ -40,6 +42,11 @@ public class RepositoryStubImpl extends
 
     private static Repository client;
 
+    private static final String ACCESS_CONTROL_PROVIDER_PROPERTIES = "accessControlProvider.properties";
+
+    // TODO
+    private static final String PROPERTIES_PROTECTED_ITEM_REMOVE_HANDLERS= "protectedHandlers.properties";
+    
     public RepositoryStubImpl(Properties env) {
         super(env);
     }
@@ -74,6 +81,8 @@ public class RepositoryStubImpl extends
             holder.setInitParameter(
                     JCRWebdavServerServlet.INIT_PARAM_MISSING_AUTH_MAPPING,
                     "");
+            holder.setInitParameter(JcrRemotingServlet.INIT_PARAM_PROTECTED_HANDLERS_CONFIG, 
+                    PROPERTIES_PROTECTED_ITEM_REMOVE_HANDLERS);
 
             Context context = new Context(server, "/");
             context.addServlet(holder, "/*");
@@ -88,8 +97,13 @@ public class RepositoryStubImpl extends
 
         if (client == null) {
             try {
-                client = JcrUtils.getRepository(
-                        "http://localhost:" + connector.getLocalPort() + "/");
+                String uri = "http://localhost:" + connector.getLocalPort() + "/";
+                Map<String, String> parameters = new HashMap<String, String>();
+                parameters.put(JcrUtils.REPOSITORY_URI, uri);
+                // TODO
+                parameters.put(ACCESS_CONTROL_PROVIDER_PROPERTIES, "accessControlProvider.properties");
+                
+                client = JcrUtils.getRepository(parameters);
             } catch (Exception e) {
                 throw new RepositoryStubException(e);
             }

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/WorkspaceManager.java Thu Dec 18 10:43:31 2014
@@ -47,6 +47,8 @@ import org.apache.jackrabbit.jcr2spi.con
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyEventListener;
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManagerImpl;
+import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
+import org.apache.jackrabbit.jcr2spi.hierarchy.PropertyEntry;
 import org.apache.jackrabbit.jcr2spi.nodetype.EffectiveNodeTypeProvider;
 import org.apache.jackrabbit.jcr2spi.nodetype.ItemDefinitionProvider;
 import org.apache.jackrabbit.jcr2spi.nodetype.ItemDefinitionProviderImpl;
@@ -79,6 +81,7 @@ import org.apache.jackrabbit.jcr2spi.ope
 import org.apache.jackrabbit.jcr2spi.operation.ResolveMergeConflict;
 import org.apache.jackrabbit.jcr2spi.operation.Restore;
 import org.apache.jackrabbit.jcr2spi.operation.SetMixin;
+import org.apache.jackrabbit.jcr2spi.operation.SetTree;
 import org.apache.jackrabbit.jcr2spi.operation.SetPrimaryType;
 import org.apache.jackrabbit.jcr2spi.operation.SetPropertyValue;
 import org.apache.jackrabbit.jcr2spi.operation.Update;
@@ -90,6 +93,7 @@ import org.apache.jackrabbit.jcr2spi.sta
 import org.apache.jackrabbit.jcr2spi.state.ItemState;
 import org.apache.jackrabbit.jcr2spi.state.ItemStateFactory;
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.jcr2spi.state.PropertyState;
 import org.apache.jackrabbit.jcr2spi.state.Status;
 import org.apache.jackrabbit.jcr2spi.state.TransientISFactory;
 import org.apache.jackrabbit.jcr2spi.state.TransientItemStateFactory;
@@ -115,6 +119,8 @@ import org.apache.jackrabbit.spi.QueryIn
 import org.apache.jackrabbit.spi.RepositoryService;
 import org.apache.jackrabbit.spi.SessionInfo;
 import org.apache.jackrabbit.spi.Subscription;
+import org.apache.jackrabbit.spi.Tree;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.spi.commons.nodetype.NodeTypeStorage;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -925,6 +931,38 @@ public class WorkspaceManager
             }
         }
 
+        /**
+         * @see OperationVisitor#visit(org.apache.jackrabbit.jcr2spi.operation.SetTree)
+         */
+        public void visit(SetTree operation) throws RepositoryException {
+            NodeState treeState = operation.getTreeState();
+            Tree tree = service.createTree(sessionInfo, batch, treeState.getName(), treeState.getNodeTypeName(), treeState.getUniqueID());
+            populateTree(tree, treeState.getNodeEntry());
+            batch.setTree(operation.getParentId(), tree);
+        }
+
+        private void populateTree(Tree tree, NodeEntry nodeEntry) throws RepositoryException {
+            Iterator<PropertyEntry> pEntries = nodeEntry.getPropertyEntries();
+            while (pEntries.hasNext()) {
+                PropertyState ps = pEntries.next().getPropertyState();
+                if (!NameConstants.JCR_PRIMARYTYPE.equals(ps.getName()) && !NameConstants.JCR_UUID.equals(ps.getName())) {
+                    if (ps.isMultiValued()) {
+                        tree.addProperty(ps.getName(), ps.getType(), ps.getValues());
+                    } else {
+                        tree.addProperty(ps.getName(), ps.getType(), ps.getValue());
+                    }
+                }
+            }
+
+            Iterator<NodeEntry> nEntries = nodeEntry.getNodeEntries();
+            while (nEntries.hasNext()) {
+                NodeEntry child = nEntries.next();
+                NodeState childState = child.getNodeState();
+                Tree childTree = tree.addChild(childState.getName(), childState.getNodeTypeName(), childState.getUniqueID());
+                populateTree(childTree, child);
+            }
+        }
+
         /**
          * @see OperationVisitor#visit(Clone)
          */

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddNode.java Thu Dec 18 10:43:31 2014
@@ -56,9 +56,8 @@ public class AddNode extends TransientOp
         this(parentState, nodeName, nodeTypeName, uuid, DEFAULT_OPTIONS);
     }
 
-    private AddNode(NodeState parentState, Name nodeName, Name nodeTypeName,
-                    String uuid, int options)
-            throws RepositoryException {
+    AddNode(NodeState parentState, Name nodeName, Name nodeTypeName,
+            String uuid, int options) throws RepositoryException {
         super(options);
         this.parentId = parentState.getNodeId();
         this.parentState = parentState;

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/AddProperty.java Thu Dec 18 10:43:31 2014
@@ -49,10 +49,10 @@ public class AddProperty extends Transie
                         QPropertyDefinition definition) throws RepositoryException {
         this(parentState, propName, propertyType, values, definition, DEFAULT_OPTIONS);
     }
-    
-    private AddProperty(NodeState parentState, Name propName,
-                        int propertyType, QValue[] values,
-                        QPropertyDefinition definition, int options) throws RepositoryException {
+
+    AddProperty(NodeState parentState, Name propName,
+                int propertyType, QValue[] values,
+                QPropertyDefinition definition, int options) throws RepositoryException {
         super(options);
         this.parentId = parentState.getNodeId();
         this.parentState = parentState;

Added: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/IgnoreOperation.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/IgnoreOperation.java?rev=1646435&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/IgnoreOperation.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/IgnoreOperation.java Thu Dec 18 10:43:31 2014
@@ -0,0 +1,25 @@
+/*
+ * 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.jackrabbit.jcr2spi.operation;
+
+/**
+ * Marker interface that represent operations which must be ignored
+ * by the <code>SessionItemStateManager</code> for building the final ChangeLog. Instances
+ * of <code>IgnoreOperation</code> never appear in the ChangeLog.
+ */
+public interface IgnoreOperation {
+}

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/OperationVisitor.java Thu Dec 18 10:43:31 2014
@@ -51,6 +51,8 @@ public interface OperationVisitor {
 
     public void visit(ReorderNodes operation) throws RepositoryException;
 
+    public void visit(SetTree operation) throws RepositoryException;
+
     public void visit(Clone operation) throws NoSuchWorkspaceException, LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException;
 
     public void visit(Copy operation) throws NoSuchWorkspaceException, LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException;
@@ -102,4 +104,4 @@ public interface OperationVisitor {
      * @since JCR 2.0
      */
     public void visit(CreateConfiguration operation) throws RepositoryException;
-}
\ No newline at end of file
+}

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/Remove.java Thu Dec 18 10:43:31 2014
@@ -25,16 +25,12 @@ import org.apache.jackrabbit.jcr2spi.sta
 import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
 import org.apache.jackrabbit.spi.ItemId;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * <code>Remove</code>...
  */
 public class Remove extends TransientOperation {
 
-    private static Logger log = LoggerFactory.getLogger(Remove.class);
-
     private static final int REMOVE_OPTIONS =
             ItemStateValidator.CHECK_LOCK
             | ItemStateValidator.CHECK_VERSIONING
@@ -44,10 +40,6 @@ public class Remove extends TransientOpe
     protected ItemState removeState;
     protected NodeState parent;
 
-    private Remove(ItemState removeState, NodeState parent) throws RepositoryException {
-        this(removeState, parent, REMOVE_OPTIONS);
-    }
-
     private Remove(ItemState removeState, NodeState parent, int options) throws RepositoryException {
         super(options);
         this.removeId = removeState.getId();
@@ -101,11 +93,15 @@ public class Remove extends TransientOpe
 
     //------------------------------------------------------------< Factory >---
     public static Operation create(ItemState state) throws RepositoryException {
+        return create(state, REMOVE_OPTIONS);
+    }
+
+    public static Operation create(ItemState state, int options) throws RepositoryException {
         if (state.isNode() && ((NodeState) state).getDefinition().allowsSameNameSiblings()) {
             // in case of SNS-siblings make sure the parent hierarchy entry has
             // its child entries loaded.
             assertChildNodeEntries(state.getParent());
         }
-        return new Remove(state, state.getParent());
+        return new Remove(state, state.getParent(), options);
     }
 }
\ No newline at end of file

Added: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetTree.java?rev=1646435&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetTree.java (added)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/operation/SetTree.java Thu Dec 18 10:43:31 2014
@@ -0,0 +1,195 @@
+/*
+ * 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.jackrabbit.jcr2spi.operation;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import javax.jcr.AccessDeniedException;
+import javax.jcr.ItemExistsException;
+import javax.jcr.RepositoryException;
+import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.lock.LockException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.version.VersionException;
+
+import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
+import org.apache.jackrabbit.jcr2spi.state.NodeState;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.QValue;
+
+public class SetTree extends TransientOperation {
+ 
+    /**
+     * List of operations added by this SetPolicy operation.
+     */
+    private final List<Operation> operations = new ArrayList<Operation>();
+        
+    private final NodeState treeState;
+
+    private SetTree(NodeState treeState) throws RepositoryException {
+        super(ItemStateValidator.CHECK_NONE);
+        this.treeState = treeState;
+    }
+
+    private SetTree(NodeState parentState, Name nodeName, Name nodeTypeName, String uuid) throws RepositoryException {
+        super(ItemStateValidator.CHECK_NONE);
+        Operation addNode = InternalAddNode.create(parentState, nodeName, nodeTypeName, uuid);
+        operations.add(addNode);
+        treeState = (NodeState) ((AddNode) addNode).getAddedStates().get(0);
+    }
+
+    //-----------------------------------------------------------------< Operation >---
+    /**
+     * @param visitor
+     */
+    public void accept(OperationVisitor visitor) throws ValueFormatException, LockException, ConstraintViolationException, AccessDeniedException, ItemExistsException, UnsupportedRepositoryOperationException, VersionException, RepositoryException {
+        assert status == STATUS_PENDING;
+        visitor.visit(this);
+    }
+
+    /**
+     * Persisting a SetPolicy operation involves persisting each individual operation added
+     * by this policy. The concerned operation will assert the status and set it accordingly.
+     *
+     * @see Operation#persisted()
+     */
+    @Override
+    public void persisted() throws RepositoryException {  
+        assert status == STATUS_PENDING;
+        status = STATUS_PERSISTED;
+        for (Operation op : operations) {
+            op.persisted();
+        }
+    }
+
+    /**
+     * Undoing a SetPolicy operation involves undoing all operations added by the SetPolicy.
+     * @see Operation#undo()
+     */
+    @Override
+    public void undo() throws RepositoryException {
+        assert status == STATUS_PENDING;
+        status = STATUS_PERSISTED;
+        for (Operation op : operations) {
+            op.undo();
+        }
+    }
+
+    public NodeId getParentId() throws RepositoryException {
+        return treeState.getParent().getNodeId();
+    }
+    
+    public NodeState getParentState() throws RepositoryException {
+        return treeState.getParent();
+    }
+
+    public NodeState getTreeState() throws RepositoryException {
+        return treeState;
+    }
+
+    /**
+     * Add a child node operation to this {@code setTree} instance.
+     *
+     * @param parentState
+     * @param nodeName
+     * @param nodeTypeName
+     * @param uuid
+     * @return
+     * @throws RepositoryException
+     */
+    public Operation addChildNode(NodeState parentState, Name nodeName, Name nodeTypeName, String uuid) throws RepositoryException {
+        Operation addNode = InternalAddNode.create(parentState, nodeName, nodeTypeName, uuid);
+        operations.add(addNode);
+        return addNode;
+    }
+    /**
+     * Add a child property operation to this {@code setTree} instance.
+     *
+     * @param parentState
+     * @param propName
+     * @param propertyType
+     * @param values
+     * @param definition
+     * @return
+     * @throws RepositoryException
+     */
+    public Operation addChildProperty(NodeState parentState, Name propName,
+                                      int propertyType, QValue[] values,
+                                      QPropertyDefinition definition) throws RepositoryException {
+        Operation addProperty = new InternalAddProperty(parentState, propName, propertyType, values, definition);
+        operations.add(addProperty);
+        return addProperty;
+    }
+
+    //------------------------------------------------------------< factory >---
+
+    public static SetTree create(NodeState treeState) throws RepositoryException {
+        SetTree operation = new SetTree(treeState);
+        return operation;
+    }
+
+    public static SetTree create(NodeState parent, Name nodeName, Name nodeTypeName, String uuid) throws RepositoryException {
+        return new SetTree(parent, nodeName, nodeTypeName, uuid);
+    }
+
+    //--------------------------------------------------------------------------
+
+    /**
+     * Inner class for adding a protected node.
+     */
+    private static final class InternalAddNode extends AddNode implements IgnoreOperation {
+        /**
+         * Options that must not be violated for a successful set policy operation.
+         */
+        private final static int SET_POLICY_ADD_NODE_OPTIONS =  ItemStateValidator.CHECK_ACCESS |
+                ItemStateValidator.CHECK_LOCK |
+                ItemStateValidator.CHECK_COLLISION |
+                ItemStateValidator.CHECK_VERSIONING;
+
+        private InternalAddNode(NodeState parentState, Name nodeName, Name nodeTypeName, String uuid) throws RepositoryException {
+            super(parentState, nodeName, nodeTypeName, uuid, SET_POLICY_ADD_NODE_OPTIONS);
+        }
+
+        public static Operation create(NodeState parentState, Name nodeName, Name nodeTypeName, String uuid) throws RepositoryException {
+            assertChildNodeEntries(parentState);
+            InternalAddNode an = new InternalAddNode(parentState, nodeName, nodeTypeName, uuid);
+            return an;
+        }
+    }
+
+    /**
+     * Inner class for adding a protected property.
+     */
+    private static final class InternalAddProperty extends AddProperty implements IgnoreOperation {
+        private final static int SET_POLICY_ADD_PROPERTY_OPTIONS =  ItemStateValidator.CHECK_ACCESS |
+                ItemStateValidator.CHECK_LOCK |
+                ItemStateValidator.CHECK_COLLISION |
+                ItemStateValidator.CHECK_VERSIONING;
+
+        private InternalAddProperty(NodeState parentState, Name propName, int propertyType, QValue[] values, QPropertyDefinition definition) throws RepositoryException {
+            super(parentState, propName, propertyType, values, definition, SET_POLICY_ADD_PROPERTY_OPTIONS);
+        }
+    }
+}
+
+

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProvider.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProvider.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProvider.java Thu Dec 18 10:43:31 2014
@@ -41,7 +41,7 @@ public interface AccessControlProvider {
     void init(RepositoryConfig config, RepositoryService service);
 
     /**
-     * Then privileges corresponding to the specified names.
+     * The privileges corresponding to the specified name.
      *
      * @param sessionInfo
      * @param resolver
@@ -63,7 +63,7 @@ public interface AccessControlProvider {
      */
     Map<String, Privilege> getSupportedPrivileges(SessionInfo sessionInfo, NodeId nodeId, NamePathResolver npResolver) throws RepositoryException;
 
-    Set<Privilege> getPrivileges(SessionInfo sessionInfo, NodeId id) throws RepositoryException;
+    Set<Privilege> getPrivileges(SessionInfo sessionInfo, NodeId id, NamePathResolver npResolver) throws RepositoryException;
 
     AccessControlManager createAccessControlManager(SessionInfo sessionInfo,
                                                     UpdatableItemStateManager itemStateManager,

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProviderStub.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProviderStub.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProviderStub.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/AccessControlProviderStub.java Thu Dec 18 10:43:31 2014
@@ -57,6 +57,7 @@ public class AccessControlProviderStub {
     /**
      * Instantiates and returns a concrete AccessControlProvider implementation.
      * @param service     The repository service.
+     * @param config      The RepositoryConfig to read configuration parameters.
      * @return
      * @throws RepositoryException
      */
@@ -65,7 +66,7 @@ public class AccessControlProviderStub {
         if (className != null) {
             try {
                 Class<?> acProviderClass = Class.forName(className);
-                if (acProviderClass.isAssignableFrom(AccessControlProvider.class)) {
+                if (AccessControlProvider.class.isAssignableFrom(acProviderClass)) {
                     AccessControlProvider acProvider = (AccessControlProvider) acProviderClass.newInstance();
                     acProvider.init(config, service);
                     return acProvider;
@@ -92,7 +93,6 @@ public class AccessControlProviderStub {
                     prop.load(is);
                 } else {
                     log.debug("Fail to locate the access control provider properties file.");
-                    return null;
                 }
             } else {
                 File file = new File(providerImplProp);
@@ -104,9 +104,8 @@ public class AccessControlProviderStub {
             }
 
             // loads the concrete class to instantiate.
-            String  className = prop.getProperty(PROPERTY_ACCESSCONTROL_PROVIDER_CLASS, "");
-            if (!className.isEmpty()) {
-                return className;
+            if (prop.contains(PROPERTY_ACCESSCONTROL_PROVIDER_CLASS)) {
+                return prop.getProperty(PROPERTY_ACCESSCONTROL_PROVIDER_CLASS, null);
             } else {
                 log.debug("Missing AccessControlProvider configuration.");
                 return null;

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlManagerImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlManagerImpl.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlManagerImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlManagerImpl.java Thu Dec 18 10:43:31 2014
@@ -18,14 +18,17 @@ package org.apache.jackrabbit.jcr2spi.se
 
 import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.NamespaceException;
+
 import javax.jcr.PathNotFoundException;
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.ValueFormatException;
+import javax.jcr.security.AccessControlEntry;
 import javax.jcr.security.AccessControlException;
 import javax.jcr.security.AccessControlList;
 import javax.jcr.security.AccessControlManager;
@@ -34,33 +37,54 @@ import javax.jcr.security.AccessControlP
 import javax.jcr.security.Privilege;
 
 import org.apache.jackrabbit.commons.iterator.AccessControlPolicyIteratorAdapter;
-import org.apache.jackrabbit.jcr2spi.ItemManager;
 import org.apache.jackrabbit.jcr2spi.hierarchy.HierarchyManager;
+import org.apache.jackrabbit.jcr2spi.hierarchy.NodeEntry;
 import org.apache.jackrabbit.jcr2spi.nodetype.ItemDefinitionProvider;
+import org.apache.jackrabbit.jcr2spi.operation.AddNode;
+import org.apache.jackrabbit.jcr2spi.operation.Operation;
+import org.apache.jackrabbit.jcr2spi.operation.Remove;
+import org.apache.jackrabbit.jcr2spi.operation.SetMixin;
+import org.apache.jackrabbit.jcr2spi.operation.SetTree;
 import org.apache.jackrabbit.jcr2spi.security.authorization.AccessControlProvider;
 import org.apache.jackrabbit.jcr2spi.security.authorization.jackrabbit.AccessControlConstants;
+import org.apache.jackrabbit.jcr2spi.state.ItemStateValidator;
 import org.apache.jackrabbit.jcr2spi.state.NodeState;
 import org.apache.jackrabbit.jcr2spi.state.UpdatableItemStateManager;
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.Path;
+import org.apache.jackrabbit.spi.QPropertyDefinition;
+import org.apache.jackrabbit.spi.QValue;
 import org.apache.jackrabbit.spi.QValueFactory;
 import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.commons.conversion.NameException;
+import org.apache.jackrabbit.spi.commons.conversion.NameParser;
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Jackrabbit-core specific implementation of the {@code AccessControlManager}.
  */
 class AccessControlManagerImpl implements AccessControlManager, AccessControlConstants {
 
+    private static final Logger log = LoggerFactory.getLogger(AccessControlManagerImpl.class);
+
+    private static int REMOVE_POLICY_OPTIONS =
+            ItemStateValidator.CHECK_ACCESS |
+            ItemStateValidator.CHECK_LOCK |
+            ItemStateValidator.CHECK_COLLISION |
+            ItemStateValidator.CHECK_VERSIONING;
+    
     private final SessionInfo sessionInfo;
     private final HierarchyManager hierarchyManager;
     private final NamePathResolver npResolver;
     private final QValueFactory qvf;
     private final AccessControlProvider acProvider;
-
+    private final UpdatableItemStateManager itemStateMgr;
+    private final ItemDefinitionProvider definitionProvider;
+    
     AccessControlManagerImpl(SessionInfo sessionInfo,
                              UpdatableItemStateManager itemStateMgr,
-                             ItemManager itemManager,
                              ItemDefinitionProvider definitionProvider,
                              HierarchyManager hierarchyManager,
                              NamePathResolver npResolver,
@@ -68,13 +92,15 @@ class AccessControlManagerImpl implement
                              AccessControlProvider acProvider) {
         this.sessionInfo = sessionInfo;
         this.hierarchyManager = hierarchyManager;
+        this.itemStateMgr = itemStateMgr;
         this.npResolver = npResolver;
         this.qvf = qvf;
         this.acProvider = acProvider;
+        this.definitionProvider = definitionProvider;
     }
 
     public Privilege[] getSupportedPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
-        NodeState state = getNodeState(getQPath(absPath));
+        NodeState state = getNodeState(npResolver.getQPath(absPath));
         Map<String, Privilege> privileges = acProvider.getSupportedPrivileges(sessionInfo, state.getNodeId(), npResolver);
         return privileges.values().toArray(new Privilege[privileges.size()]);
     }
@@ -84,12 +110,12 @@ class AccessControlManagerImpl implement
     }
 
     public boolean hasPrivileges(String absPath, Privilege[] privileges) throws PathNotFoundException, RepositoryException {
-        Set<Privilege> privs = acProvider.getPrivileges(sessionInfo, getNodeState(getQPath(absPath)).getNodeId());
+        Set<Privilege> privs = acProvider.getPrivileges(sessionInfo, getNodeState(npResolver.getQPath(absPath)).getNodeId(), npResolver);
         return privs.containsAll(Arrays.asList(privileges));
     }
 
     public Privilege[] getPrivileges(String absPath) throws PathNotFoundException, RepositoryException {
-        Set<Privilege> privs = acProvider.getPrivileges(sessionInfo, getNodeState(getQPath(absPath)).getNodeId());
+        Set<Privilege> privs = acProvider.getPrivileges(sessionInfo, getNodeState(npResolver.getQPath(absPath)).getNodeId(), npResolver);
         return privs.toArray(new Privilege[privs.size()]);
     }
 
@@ -102,7 +128,7 @@ class AccessControlManagerImpl implement
         checkValidNodePath(absPath);
 
         AccessControlPolicy[] applicable = getApplicable(absPath);
-        if (applicable != null) {
+        if (applicable != null && applicable.length > 0) {
             return new AccessControlPolicyIteratorAdapter(Arrays.asList(applicable));
         } else {
             return AccessControlPolicyIteratorAdapter.EMPTY;
@@ -112,23 +138,65 @@ class AccessControlManagerImpl implement
     public AccessControlPolicy[] getPolicies(String absPath) throws RepositoryException {
         List<AccessControlList> policies = new ArrayList<AccessControlList>();
         NodeState aclNode = getAclNode(absPath);
-        final AccessControlList acl;
+        AccessControlList acl;
         
         if (aclNode != null) {
-            acl = createPolicy(aclNode, absPath);
+            acl = new AccessControlListImpl(aclNode, absPath, npResolver, qvf, this);
             policies.add(acl);
         }
         return policies.toArray(new AccessControlList[policies.size()]);
     }
-     
+
     public void setPolicy(String absPath, AccessControlPolicy policy) throws RepositoryException {
-        // TODO
-        throw new UnsupportedRepositoryOperationException("not yet implemented");
+        checkValidNodePath(absPath);
+        checkValidPolicy(policy);
+        checkAcccessControlItem(absPath);
+
+        SetTree operation;
+        NodeState aclNode = getAclNode(absPath);
+        if (aclNode == null) {
+            // policy node doesn't exist at absPath -> create one.
+            Name name = (absPath == null) ? N_REPO_POLICY : N_POLICY;
+
+            NodeState parent = null;
+            Name mixinType = null;
+            if (absPath == null) {
+                parent = getRootNodeState();
+                mixinType = NT_REP_REPO_ACCESS_CONTROLLABLE;
+            } else {
+                parent = getNodeState(absPath);
+                mixinType = NT_REP_ACCESS_CONTROLLABLE;
+            }
+            setMixin(parent, mixinType);
+
+            operation = SetTree.create(parent, name, NT_REP_ACL, null);
+            aclNode = operation.getTreeState();
+        } else {
+            Iterator<NodeEntry> it = getNodeEntry(aclNode).getNodeEntries();
+            while(it.hasNext()) {
+                it.next().transientRemove();
+            }
+            operation = SetTree.create(aclNode);
+        }
+
+        // create the entry nodes
+        for (AccessControlEntry entry : ((AccessControlListImpl) policy).getAccessControlEntries()) {
+            createAceNode(operation, aclNode, entry);
+        }
+
+        itemStateMgr.execute(operation);
     }
         
     public void removePolicy(String absPath, AccessControlPolicy policy) throws RepositoryException {
-        // TODO
-        throw new UnsupportedRepositoryOperationException("not yet implemented");
+        checkValidNodePath(absPath);
+        checkValidPolicy(policy);
+        
+        NodeState aclNode = getAclNode(absPath);        
+        if (aclNode != null) {
+            removeNode(aclNode);
+        } else {
+            throw new AccessControlException("No policy exist at "+absPath);
+        }
     }
 
     //--------------------------------------------------< private >---
@@ -149,16 +217,6 @@ class AccessControlManagerImpl implement
         return (acl == null) ? new AccessControlPolicy[0] : new AccessControlPolicy[] {acl};
     }
 
-    /**
-     * Creates an AccessControlList policy for the given acl node.
-     * @param aclNode the node for which the policy is to be created for.
-     * @param aclPath the policy path.
-     * @return
-     */
-    private AccessControlListImpl createPolicy(NodeState aclNode, String aclPath) throws RepositoryException {
-        return new AccessControlListImpl(aclNode, aclPath, npResolver, qvf, this);
-    }
-
     private NodeState getAclNode(String controlledNodePath) throws RepositoryException {
         NodeState controlledNode;
         if (controlledNodePath == null) {
@@ -182,14 +240,6 @@ class AccessControlManagerImpl implement
         }
         return acl;
     }
-
-    private Path getQPath(String name) throws RepositoryException {
-        try {
-            return npResolver.getQPath(name);
-        } catch(NamespaceException e) {
-            throw new RepositoryException(e.getMessage());
-        }
-    }
         
     /**
      * Test if the given node state is of node type
@@ -225,36 +275,144 @@ class AccessControlManagerImpl implement
         return (lst == null) ? false : lst.contains(mixinName);
     }
 
-    private NodeState getNodeState(String nodePath) throws RepositoryException {
-        return getNodeState(getQPath(nodePath));
+    /**
+     * Checks whether if the given nodePath points to an access
+     * control policy or entry node.
+     * @param nodePath
+     * @throws AccessControlException
+     * @throws RepositoryException
+     */
+    private void checkAcccessControlItem(String nodePath) throws AccessControlException, RepositoryException {
+        NodeState controlledState = getNodeState(nodePath);
+        Name ntName = controlledState.getNodeTypeName();
+        boolean isAcItem =  ntName.equals(NT_REP_ACL) ||
+                            ntName.equals(NT_REP_GRANT_ACE) ||
+                            ntName.equals(NT_REP_DENY_ACE);
+        if (isAcItem) {
+            throw new AccessControlException("The path: "+nodePath+" points to an access control content node");
+        }
+
     }
     
-    private NodeState getRootNodeState() throws RepositoryException {
+    private void createAceNode(SetTree operation, NodeState parentState, AccessControlEntry entry) throws RepositoryException {
+        AccessControlEntryImpl ace = (AccessControlEntryImpl) entry;
+        
+        String uuid = null;
+        boolean isAllow = ace.isAllow();
+        Name nodeName = getUniqueNodeName(parentState, (isAllow) ? "allow" : "deny");
+        Name nodeTypeName = (isAllow) ? NT_REP_GRANT_ACE : NT_REP_DENY_ACE;
+        NodeState aceNode = addNode(operation, parentState, nodeName, uuid, nodeTypeName);
+               
+        // add rep:principalName property
+        String valueStr = ace.getPrincipal().getName();
+        QValue value = qvf.create(valueStr, PropertyType.STRING);
+        addProperty(operation, aceNode, N_REP_PRINCIPAL_NAME, PropertyType.STRING, new QValue[] {value});
+
+        // add rep:privileges MvProperty
+        Privilege[] privs = ace.getPrivileges();
+        QValue[] vls = new QValue[privs.length];
+        Name privilegeName = null;
         try {
-            return getHierarchyManager().getRootEntry().getNodeState();
-        } catch (ItemNotFoundException e) {
+            for (int i = 0; i < privs.length; i++) {
+                privilegeName = npResolver.getQName(privs[i].getName());
+                vls[i] = qvf.create(privilegeName.toString(), PropertyType.NAME);
+            }            
+        } catch (ValueFormatException e) {
             throw new RepositoryException(e.getMessage());
         }
+
+        addProperty(operation, aceNode, N_REP_PRIVILEGES, PropertyType.NAME, vls);
+
+        // TODO: add rep:glob property            
+    }
+    
+    private NodeState getNodeState(String nodePath) throws RepositoryException {
+        return getNodeState(npResolver.getQPath(nodePath));
+    }
+    
+    private NodeState getRootNodeState() throws RepositoryException {
+        return hierarchyManager.getRootEntry().getNodeState();
     }
     
     private NodeState getNodeState(Path qPath) throws RepositoryException {
-        return getHierarchyManager().getNodeState(qPath);
+        return hierarchyManager.getNodeState(qPath);
+    }
+    
+    private NodeEntry getNodeEntry(NodeState nodeState) throws RepositoryException {
+        return hierarchyManager.getNodeEntry(nodeState.getPath());
     }
     
     private void checkValidNodePath(String absPath) throws PathNotFoundException, RepositoryException {
         if (absPath != null) {
-            Path qPath = getQPath(absPath);
+            Path qPath = npResolver.getQPath(absPath);
             if (!qPath.isAbsolute()) {
                 throw new RepositoryException("Absolute path expected. Found: " + absPath);
             }
 
-            if (getHierarchyManager().getNodeEntry(qPath).getNodeState() == null) {
+            if (hierarchyManager.getNodeEntry(qPath).getNodeState() == null) {
                 throw new PathNotFoundException(absPath);
             }
         }
     }
 
-    private HierarchyManager getHierarchyManager() {
-        return hierarchyManager;
+    private void checkValidPolicy(AccessControlPolicy policy) throws AccessControlException {
+        if (policy == null || !(policy instanceof AccessControlListImpl)) {
+            throw new AccessControlException("Policy is not applicable ");
+        }
+    }
+    
+    private NodeState addNode(SetTree treeOperation, NodeState parent, Name nodeName, String uuid, Name nodeTypeName) throws RepositoryException {
+        Operation sp = treeOperation.addChildNode(parent, nodeName, nodeTypeName, uuid);
+        itemStateMgr.execute(sp);
+        return (NodeState) ((AddNode) sp).getAddedStates().get(0);
+    }
+    
+    private void addProperty(SetTree treeOperation, NodeState parent, Name propName, int propType, QValue[] values) throws RepositoryException {
+        QPropertyDefinition definition = definitionProvider.getQPropertyDefinition(parent.getAllNodeTypeNames(), propName, propType);
+
+        Operation ap = treeOperation.addChildProperty(parent, propName, propType, values, definition);
+        itemStateMgr.execute(ap);
+    }
+    
+    private void removeNode(NodeState aclNode) throws RepositoryException {
+        Operation removePolicy = Remove.create(aclNode, REMOVE_POLICY_OPTIONS);
+        itemStateMgr.execute(removePolicy);
+    }
+    
+    private void setMixin(NodeState parent, Name mixinName) throws RepositoryException {
+        if (!isNodeType(parent, mixinName)){
+            Operation sm = SetMixin.create(parent, new Name[]{mixinName});
+            itemStateMgr.execute(sm);
+         } else {
+             log.debug(mixinName.toString()+" is already present on the given node state "+parent.getName().toString());
+         }
+    }
+    
+    // copied from jackrabbit-core ACLEditor
+    /**
+     * Create a unique valid name for the Permission nodes to be save.
+     *
+     * @param node a name for the child is resolved
+     * @param name if missing the {@link #DEFAULT_ACE_NAME} is taken
+     * @return the name
+     * @throws RepositoryException if an error occurs
+     */
+    private Name getUniqueNodeName(NodeState node, String name) throws RepositoryException {
+            
+        try {        
+            NameParser.checkFormat(name);
+        } catch (NameException e) {                        
+            log.debug("Invalid path name for Permission: " + name + ".");       
+        }
+
+        int i = 0;
+        String check = name;
+        Name n = npResolver.getQName(check);
+        while (node.hasChildNodeEntry(n, 1)) {
+            check = name + i;
+            n = npResolver.getQName(check);
+            i++;
+        }
+        return n;
     }
 }

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlProviderImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlProviderImpl.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlProviderImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlProviderImpl.java Thu Dec 18 10:43:31 2014
@@ -17,10 +17,10 @@
 package org.apache.jackrabbit.jcr2spi.security.authorization.jackrabbit.acl;
 
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 import javax.jcr.RepositoryException;
-import javax.jcr.UnsupportedRepositoryOperationException;
 import javax.jcr.security.AccessControlException;
 import javax.jcr.security.AccessControlManager;
 import javax.jcr.security.Privilege;
@@ -76,9 +76,14 @@ public class AccessControlProviderImpl i
     }
 
     @Override
-    public Set<Privilege> getPrivileges(SessionInfo sessionInfo, NodeId id) throws RepositoryException {
-        // TODO
-        throw new UnsupportedRepositoryOperationException("not yet implemented");
+    public Set<Privilege> getPrivileges(SessionInfo sessionInfo, NodeId id, NamePathResolver npResolver) throws RepositoryException {
+        PrivilegeDefinition[] defs = service.getPrivileges(sessionInfo, id);
+        Set<Privilege> privileges = new HashSet<Privilege>(defs.length);
+        for (PrivilegeDefinition def : defs) {
+            Privilege p = new PrivilegeImpl(def, defs, npResolver);
+            privileges.add(p);
+        }
+        return privileges;        
     }
 
     @Override
@@ -88,7 +93,7 @@ public class AccessControlProviderImpl i
             ItemManager itemManager,
             ItemDefinitionProvider definitionProvider,
             HierarchyManager hierarchyManager, NamePathResolver npResolver) throws RepositoryException {
-        return new AccessControlManagerImpl(sessionInfo, itemStateManager, itemManager, definitionProvider, hierarchyManager, npResolver, service.getQValueFactory(), this);
+        return new AccessControlManagerImpl(sessionInfo, itemStateManager, definitionProvider, hierarchyManager, npResolver, service.getQValueFactory(), this);
     }
 
     //--------------------------------------------------------------------------

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/state/SessionItemStateManager.java Thu Dec 18 10:43:31 2014
@@ -45,12 +45,14 @@ import org.apache.jackrabbit.jcr2spi.nod
 import org.apache.jackrabbit.jcr2spi.nodetype.ItemDefinitionProvider;
 import org.apache.jackrabbit.jcr2spi.operation.AddNode;
 import org.apache.jackrabbit.jcr2spi.operation.AddProperty;
+import org.apache.jackrabbit.jcr2spi.operation.IgnoreOperation;
 import org.apache.jackrabbit.jcr2spi.operation.Move;
 import org.apache.jackrabbit.jcr2spi.operation.Operation;
 import org.apache.jackrabbit.jcr2spi.operation.OperationVisitor;
 import org.apache.jackrabbit.jcr2spi.operation.Remove;
 import org.apache.jackrabbit.jcr2spi.operation.ReorderNodes;
 import org.apache.jackrabbit.jcr2spi.operation.SetMixin;
+import org.apache.jackrabbit.jcr2spi.operation.SetTree;
 import org.apache.jackrabbit.jcr2spi.operation.SetPrimaryType;
 import org.apache.jackrabbit.jcr2spi.operation.SetPropertyValue;
 import org.apache.jackrabbit.jcr2spi.operation.TransientOperationVisitor;
@@ -245,7 +247,9 @@ public class SessionItemStateManager ext
         List<ItemState> newStates = addNodeState(parent, operation.getNodeName(), operation.getNodeTypeName(), operation.getUuid(), def, operation.getOptions());
         operation.addedState(newStates);
 
-        transientStateMgr.addOperation(operation);
+        if (!(operation instanceof IgnoreOperation)) {
+            transientStateMgr.addOperation(operation);
+        }
     }
 
     /**
@@ -265,6 +269,15 @@ public class SessionItemStateManager ext
 
         addPropertyState(parent, propertyName, targetType, operation.getValues(), pDef, operation.getOptions());
 
+        if (!(operation instanceof IgnoreOperation)) {
+            transientStateMgr.addOperation(operation);
+        }
+    }
+
+    /**
+     * @see OperationVisitor#visit(org.apache.jackrabbit.jcr2spi.operation.SetTree)
+     */
+    public void visit(SetTree operation) throws RepositoryException {
         transientStateMgr.addOperation(operation);
     }
 

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/AbstractJCR2SPITest.java Thu Dec 18 10:43:31 2014
@@ -67,6 +67,7 @@ import org.apache.jackrabbit.spi.Reposit
 import org.apache.jackrabbit.spi.SessionInfo;
 import org.apache.jackrabbit.spi.Subscription;
 import org.apache.jackrabbit.spi.Path.Element;
+import org.apache.jackrabbit.spi.Tree;
 import org.apache.jackrabbit.spi.commons.AbstractReadableRepositoryService;
 import org.apache.jackrabbit.spi.commons.ItemInfoBuilder;
 import org.apache.jackrabbit.spi.commons.ItemInfoBuilder.NodeInfoBuilder;
@@ -172,11 +173,17 @@ public abstract class AbstractJCR2SPITes
                 return AbstractJCR2SPITest.this.getPrivilegeDefinitions(sessionInfo);
             }
 
+            @Override
             public PrivilegeDefinition[] getSupportedPrivileges(SessionInfo sessionInfo, NodeId nodeId) throws RepositoryException {
                 return AbstractJCR2SPITest.this.getSupportedPrivileges(sessionInfo, nodeId);
             }
 
             @Override
+            public PrivilegeDefinition[] getPrivileges(SessionInfo sessionInfo, NodeId nodeId) throws RepositoryException {
+                return AbstractJCR2SPITest.this.getPrivileges(sessionInfo, nodeId);
+            }
+            
+            @Override
             public NodeInfo getNodeInfo(SessionInfo sessionInfo, NodeId nodeId) throws ItemNotFoundException,
                     RepositoryException {
 
@@ -283,6 +290,11 @@ public abstract class AbstractJCR2SPITes
             SessionInfo sessionInfo, NodeId nodeId) throws RepositoryException {
         return repositoryService.getSupportedPrivileges(sessionInfo, nodeId);
     }
+    
+    public PrivilegeDefinition[] getPrivileges(
+            SessionInfo sessionInfo, NodeId nodeId) throws RepositoryException {
+        return repositoryService.getPrivileges(sessionInfo, nodeId);
+    }
     //-----------------------------------< SessionInfo creation and release >---
 
     public SessionInfo obtain(Credentials credentials, String workspaceName) throws RepositoryException {
@@ -357,6 +369,10 @@ public abstract class AbstractJCR2SPITes
         repositoryService.submit(batch);
     }
 
+    @Override
+    public Tree createTree(SessionInfo sessionInfo, Batch batch, Name nodeName, Name primaryTypeName, String uniqueId) throws RepositoryException {
+        return repositoryService.createTree(sessionInfo, batch, nodeName, primaryTypeName, uniqueId);
+    }
 
     //-------------------------------------------------------------< Import >---
 

Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlListImplTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlListImplTest.java?rev=1646435&r1=1646434&r2=1646435&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlListImplTest.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/security/authorization/jackrabbit/acl/AccessControlListImplTest.java Thu Dec 18 10:43:31 2014
@@ -36,7 +36,6 @@ import org.apache.jackrabbit.spi.commons
 import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 import org.apache.jackrabbit.spi.commons.value.QValueFactoryImpl;
 import org.apache.jackrabbit.test.api.security.AbstractAccessControlTest;
-import org.junit.Test;
 
 /**
  * Tests the functionality of the JCR AccessControlList API implementation. The
@@ -45,12 +44,13 @@ import org.junit.Test;
  */
 public class AccessControlListImplTest extends AbstractAccessControlTest {
 
-    private NamePathResolver resolver;
     private QValueFactory vFactory;
 
     private Principal unknownPrincipal;
     private Principal knownPrincipal;
 
+    private NamePathResolver resolver;
+
     @Override
     public void setUp() throws Exception {
         super.setUp();
@@ -76,7 +76,6 @@ public class AccessControlListImplTest e
         return Collections.<String, Value> emptyMap();
     }
 
-    @Test
     public void testAddingDifferentEntries() throws Exception {
         JackrabbitAccessControlList acl = createAccessControList(testRoot);
 
@@ -109,15 +108,13 @@ public class AccessControlListImplTest e
         
     }
 
-    @Test
     public void testMultipleEntryEffect() throws Exception {
         JackrabbitAccessControlList acl = createAccessControList(testRoot);
         Privilege[] privileges = privilegesFromName(Privilege.JCR_READ);
 
         // GRANT 'read' privilege to the Admin user -> list now contains one
         // allow entry
-        boolean actual = acl.addAccessControlEntry(unknownPrincipal, privileges);
-        assertTrue(actual);
+        assertTrue(acl.addAccessControlEntry(unknownPrincipal, privileges));
 
         // policy contains a single entry
         assertEquals(1, acl.size());
@@ -131,28 +128,24 @@ public class AccessControlListImplTest e
         // GRANT 'add_child_node' privilege for the admin user -> same entry but
         // with an additional 'add_child_node' privilege.
         privileges = privilegesFromNames(new String[] {Privilege.JCR_ADD_CHILD_NODES, Privilege.JCR_READ });
+        assertTrue(acl.addAccessControlEntry(unknownPrincipal, privileges));
 
-        actual = acl.addAccessControlEntry(unknownPrincipal, privileges);
-        assertTrue(actual);
-
-        // A new Entry wasn't added -> the existing entry was modified ->
-        // entries count should still be 1.
-        assertEquals(1, acl.size());
+        // A new Entry was added -> entries count should be 2.
+        assertEquals(2, acl.size());
 
         // The single entry should now contain both 'read' and 'add_child_nodes'
         // privileges for the same principal.
-        assertEquals(2, acl.getAccessControlEntries()[0].getPrivileges().length);
+        assertEquals(1, acl.getAccessControlEntries()[0].getPrivileges().length);
+        assertEquals(2, acl.getAccessControlEntries()[1].getPrivileges().length);
 
         // adding a privilege that's already granted for the same principal ->
         // again modified as the client doesn't care about possible compaction the
         // server may want to make.
         privileges = privilegesFromNames(new String[] { Privilege.JCR_READ });
-        actual = acl.addAccessControlEntry(unknownPrincipal, privileges);
-        assertTrue(actual);
+        assertTrue(acl.addAccessControlEntry(unknownPrincipal, privileges));
 
         // revoke the read privilege
-        actual = acl.addEntry(unknownPrincipal, privileges, false, createEmptyRestriction());
-        assertTrue("Fail to revoke read privilege", actual);
+        assertTrue("Fail to revoke read privilege", acl.addEntry(unknownPrincipal, privileges, false, createEmptyRestriction()));
 
         // should now be two entries -> an allow entry + a deny entry
         assertEquals(2, acl.size());
@@ -182,12 +175,9 @@ public class AccessControlListImplTest e
 
         // GRANT a read privilege
         privileges = privilegesFromNames(new String[] { Privilege.JCR_READ });
-        actual = acl.addAccessControlEntry(unknownPrincipal, privileges);
-        assertTrue("New Entry -> grants read privilege", actual);
-
-        actual = acl.addEntry(unknownPrincipal, privileges, false, createEmptyRestriction());
-        assertTrue("Fail to revoke the read privilege", actual);
+        assertTrue("New Entry -> grants read privilege", acl.addAccessControlEntry(unknownPrincipal, privileges));
 
+        assertTrue("Fail to revoke the read privilege", acl.addEntry(unknownPrincipal, privileges, false, createEmptyRestriction()));
         Assert.assertEquals(1, acl.size());
     }
     



Mime
View raw message