You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by tr...@apache.org on 2014/01/22 06:49:46 UTC

svn commit: r1560258 - in /jackrabbit/commons/filevault/trunk/vault-core/src: main/java/org/apache/jackrabbit/vault/fs/impl/io/ main/java/org/apache/jackrabbit/vault/fs/io/ main/java/org/apache/jackrabbit/vault/util/ test/java/org/apache/jackrabbit/vau...

Author: tripod
Date: Wed Jan 22 05:49:45 2014
New Revision: 1560258

URL: http://svn.apache.org/r1560258
Log:
JCRVLT-25 Implement AccessControllHandling MERGE and MERGE_PRESERVE

Added:
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAdapter.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/mode_ac_test_c_merge.zip   (with props)
    jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/mode_ac_test_d.zip   (with props)
    jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/oak_ac_content_test.zip   (with props)
Modified:
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestACLAndMerge.java

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAdapter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAdapter.java?rev=1560258&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAdapter.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewAdapter.java Wed Jan 22 05:49:45 2014
@@ -0,0 +1,48 @@
+/*************************************************************************
+ * 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.vault.fs.impl.io;
+
+import org.apache.jackrabbit.vault.util.DocViewNode;
+import org.xml.sax.SAXException;
+
+/**
+ * {@code DocViewAdapter} is used by the {@link org.apache.jackrabbit.vault.fs.impl.io.DocViewSAXImporter} to handle
+ * special content that is not importable using "normal" JCR calls. For example users and other protected content
+ * needs to be imported using the {@link javax.jcr.Session#importXML(String, java.io.InputStream, int)} or similar.
+ */
+public interface DocViewAdapter {
+
+    /**
+     * Start node is invoked when the importer descends into an element.
+     * @param node the node
+     * @throws SAXException if an error occurrs
+     */
+    public void startNode(DocViewNode node) throws SAXException;
+
+    /**
+     * Ends node is invoked when the importer ascends from an element.
+     * @throws SAXException if an error occurrs.
+     */
+    public void endNode() throws SAXException;
+
+    /**
+     * Is called by the importer if the adapter is no longer used and must finalize the import.
+     * @throws SAXException if an error occurrs.
+     */
+    public void close() throws SAXException;
+
+}
\ No newline at end of file

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java?rev=1560258&r1=1560257&r2=1560258&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/DocViewSAXImporter.java Wed Jan 22 05:49:45 2014
@@ -46,9 +46,7 @@ import javax.jcr.nodetype.NodeType;
 
 import org.apache.jackrabbit.spi.Name;
 import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
-import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
 import org.apache.jackrabbit.spi.commons.name.NameConstants;
-import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
 import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
 import org.apache.jackrabbit.util.ISO9075;
 import org.apache.jackrabbit.vault.fs.PropertyValueArtifact;
@@ -64,6 +62,7 @@ import org.apache.jackrabbit.vault.fs.io
 import org.apache.jackrabbit.vault.fs.spi.ACLManagement;
 import org.apache.jackrabbit.vault.fs.spi.ServiceProviderFactory;
 import org.apache.jackrabbit.vault.fs.spi.UserManagement;
+import org.apache.jackrabbit.vault.util.DocViewNode;
 import org.apache.jackrabbit.vault.util.DocViewProperty;
 import org.apache.jackrabbit.vault.util.JcrConstants;
 import org.apache.jackrabbit.vault.util.MimeTypes;
@@ -588,7 +587,7 @@ public class DocViewSAXImporter extends 
             Node node = stack.getNode();
             if (node == null) {
                 stack = stack.push(null);
-                SysViewTransformer xform = stack.getTransformer();
+                DocViewAdapter xform = stack.getAdapter();
                 if (xform != null) {
                     DocViewNode ni = new DocViewNode(name, label, attributes, npResolver);
                     xform.startNode(ni);
@@ -608,16 +607,14 @@ public class DocViewSAXImporter extends 
                     try {
                         DocViewNode ni = new DocViewNode(name, label, attributes, npResolver);
                         if (aclManagement.isACLNodeType(ni.primary)) {
-                            if (aclHandling == AccessControlHandling.OVERWRITE
-                                    || aclHandling == AccessControlHandling.MERGE
-                                    || aclHandling == AccessControlHandling.MERGE_PRESERVE && !node.hasNode(ni.name)) {
-                                log.debug("ACL element detected. starting sysview transformation {}/{}", node.getPath(), name);
+                            if (aclHandling != AccessControlHandling.CLEAR && aclHandling != AccessControlHandling.IGNORE) {
+                                log.debug("ACL element detected. starting special transformation {}/{}", node.getPath(), name);
                                 if (aclManagement.ensureAccessControllable(node)) {
                                     log.info("Adding ACL element to non ACL parent - adding mixin: {}", node.getPath());
                                 }
                                 stack = stack.push(null);
-                                stack.transformer = new SysViewTransformer(node);
-                                stack.transformer.startNode(ni);
+                                stack.adapter = new JackrabbitACLImporter(node, aclHandling);
+                                stack.adapter.startNode(ni);
                                 importInfo.onCreated(node.getPath() + "/" + ni.name);
                             } else {
                                 stack = stack.push(null);
@@ -650,8 +647,8 @@ public class DocViewSAXImporter extends 
                             } else {
                                 log.debug("Authorizable element detected. starting sysview transformation {}/{}", node.getPath(), name);
                                 stack = stack.push(null);
-                                stack.transformer = new SysViewTransformer(node);
-                                stack.transformer.startNode(ni);
+                                stack.adapter = new JcrSysViewTransformer(node);
+                                stack.adapter.startNode(ni);
                                 importInfo.onCreated(node.getPath() + "/" + ni.name);
                             }
                         } else {
@@ -1057,14 +1054,14 @@ public class DocViewSAXImporter extends 
             NodeNameList childNames = stack.getChildNames();
             Node node = stack.getNode();
             if (node == null) {
-                SysViewTransformer xform = stack.getTransformer();
-                if (xform != null) {
-                    xform.endNode();
+                DocViewAdapter adapter = stack.getAdapter();
+                if (adapter != null) {
+                    adapter.endNode();
                 }
                 // close transformer if last in stack
-                if (stack.transformer != null) {
-                    stack.transformer.close();
-                    stack.transformer = null;
+                if (stack.adapter != null) {
+                    stack.adapter.close();
+                    stack.adapter = null;
                     log.debug("Sysview transformation complete.");
                 }
             } else {
@@ -1238,9 +1235,9 @@ public class DocViewSAXImporter extends 
         private boolean isCheckedOut;
 
         /**
-         * sysview handler for special content
+         * adapter for special content
          */
-        private SysViewTransformer transformer;
+        private DocViewAdapter adapter;
 
         public StackElement(DocViewSAXImporter.StackElement parent, Node node) throws RepositoryException {
             this.node = node;
@@ -1297,112 +1294,15 @@ public class DocViewSAXImporter extends 
             return parent;
         }
 
-        public void setTransformer(SysViewTransformer transformer) {
-            this.transformer = transformer;
-        }
-
-        public SysViewTransformer getTransformer() {
-            if (transformer != null) {
-                return transformer;
+        public DocViewAdapter getAdapter() {
+            if (adapter != null) {
+                return adapter;
             }
-            return parent == null ? null : parent.getTransformer();
+            return parent == null ? null : parent.getAdapter();
         }
 
     }
 
-    private static class SysViewTransformer {
-
-        /**
-         * sysview handler for special content
-         */
-        private ContentHandler handler;
-
-        private SysViewTransformer(Node node) throws RepositoryException, SAXException {
-            Session session = node.getSession();
-            handler = session.getImportContentHandler(
-                    node.getPath(),
-                    ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
-            // first define the current namespaces
-            String[] prefixes = session.getNamespacePrefixes();
-            handler.startDocument();
-            for (String prefix: prefixes) {
-                handler.startPrefixMapping(prefix, session.getNamespaceURI(prefix));
-            }
-        }
-
-        public void close() throws SAXException {
-            handler.endDocument();
-        }
-
-        public void startNode(DocViewNode ni) throws SAXException {
-            log.debug("Transforming element to sysview {}", ni.name);
-
-            AttributesImpl attrs = new AttributesImpl();
-
-            attrs.addAttribute(Name.NS_SV_URI, "name", "sv:name", "CDATA", ni.name);
-            handler.startElement(Name.NS_SV_URI, "node", "sv:node", attrs);
-
-            // add the properties
-            for (DocViewProperty p: ni.props.values()) {
-                if (p != null && p.values != null) {
-                    attrs = new AttributesImpl();
-                    attrs.addAttribute(Name.NS_SV_URI, "name", "sv:name", "CDATA", p.name);
-                    attrs.addAttribute(Name.NS_SV_URI, "type", "sv:type", "CDATA", PropertyType.nameFromValue(p.type));
-                    handler.startElement(Name.NS_SV_URI, "property", "sv:property", attrs);
-                    for (String v: p.values) {
-                        handler.startElement(Name.NS_SV_URI, "value", "sv:value", EMPTY_ATTRIBUTES);
-                        handler.characters(v.toCharArray(), 0, v.length());
-                        handler.endElement(Name.NS_SV_URI, "value", "sv:value");
-                    }
-                    handler.endElement(Name.NS_SV_URI, "property", "sv:property");
-                }
-            }
-        }
-
-        public void endNode() throws SAXException {
-            handler.endElement(Name.NS_SV_URI, "node", "sv:node");
-        }
-    }
-
-    /**
-     * <code>DocViewNode</code>...
-     */
-    private static class DocViewNode {
-
-        private final String name;
-        private final String label;
-        private final Map<String, DocViewProperty> props = new HashMap<String, DocViewProperty>();
-        private String uuid = null;
-        private String[] mixins = null;
-        private String primary = null;
-
-        public DocViewNode(String name, String label, Attributes attributes,
-                           NamePathResolver npResolver)
-                throws NamespaceException {
-            this.name = name;
-            this.label = label;
-            for (int i = 0; i < attributes.getLength(); i++) {
-                // ignore non CDATA attributes
-                if (!attributes.getType(i).equals("CDATA")) {
-                    continue;
-                }
-                Name pName = NameFactoryImpl.getInstance().create(
-                        attributes.getURI(i),
-                        ISO9075.decode(attributes.getLocalName(i)));
-                DocViewProperty info = DocViewProperty.parse(
-                        npResolver.getJCRName(pName),
-                        attributes.getValue(i));
-                props.put(info.name, info);
-                if (pName.equals(NameConstants.JCR_UUID)) {
-                    uuid = info.values[0];
-                } else if (pName.equals(NameConstants.JCR_PRIMARYTYPE)) {
-                    primary = info.values[0];
-                } else if (pName.equals(NameConstants.JCR_MIXINTYPES)) {
-                    mixins = info.values;
-                }
-            }
-        }
-    }
 }
 
 

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java?rev=1560258&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JackrabbitACLImporter.java Wed Jan 22 05:49:45 2014
@@ -0,0 +1,256 @@
+/*************************************************************************
+ * 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.vault.fs.impl.io;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Stack;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.security.AccessControlEntry;
+import javax.jcr.security.AccessControlManager;
+import javax.jcr.security.AccessControlPolicy;
+import javax.jcr.security.AccessControlPolicyIterator;
+import javax.jcr.security.Privilege;
+
+import org.apache.jackrabbit.api.JackrabbitSession;
+import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.principal.PrincipalManager;
+import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
+import org.apache.jackrabbit.vault.util.DocViewNode;
+import org.apache.jackrabbit.vault.util.DocViewProperty;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.SAXException;
+
+/**
+ * Implements a doc view adapter that reads the ACL information of the docview hierarchy and applies it to the
+ * underlying repository, based on the {@link org.apache.jackrabbit.vault.fs.io.AccessControlHandling}
+ */
+public class JackrabbitACLImporter implements DocViewAdapter {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(JackrabbitACLImporter.class);
+
+    private final Node accessControlledNode;
+
+    private final AccessControlHandling aclHandling;
+
+    private final AccessControlManager acMgr;
+
+    private final PrincipalManager pMgr;
+
+    private Map<String, List<ACE>> aceMap = new HashMap<String, List<ACE>>();
+
+    private ACE currentACE;
+
+    private static enum State {
+        INITIAL,
+        ACL,
+        ACE,
+        RESTRICTION,
+        ERROR,
+    }
+
+    private final Stack<State> states = new Stack<State>();
+
+    public JackrabbitACLImporter(Node accessControlledNode, AccessControlHandling aclHandling) throws RepositoryException {
+        if (aclHandling == AccessControlHandling.CLEAR || aclHandling == AccessControlHandling.IGNORE) {
+            throw new RepositoryException("Error while reading access control content: unsupported AccessControlHandling: " + aclHandling);
+        }
+        this.accessControlledNode = accessControlledNode;
+        this.acMgr = accessControlledNode.getSession().getAccessControlManager();
+        this.pMgr = ((JackrabbitSession) accessControlledNode.getSession()).getPrincipalManager();
+        this.aclHandling = aclHandling;
+        this.states.push(State.INITIAL);
+    }
+
+    public void startNode(DocViewNode node) throws SAXException {
+        State state = states.peek();
+        switch (state) {
+            case INITIAL:
+                if ("rep:ACL".equals(node.primary)) {
+                    state = State.ACL;
+                } else {
+                    log.error("Error while reading access control content: Expected rep:ACL but was: {}", node.primary);
+                    state = State.ERROR;
+                }
+                break;
+
+            case ACL:
+                try {
+                    currentACE = new ACE(node);
+                    List<ACE> list = aceMap.get(currentACE.principalName);
+                    if (list == null) {
+                        list = new ArrayList<ACE>();
+                        aceMap.put(currentACE.principalName, list);
+                    }
+                    list.add(currentACE);
+                    state = State.ACE;
+                } catch (IllegalArgumentException e) {
+                    log.error("Error while reading access control content: {}", e);
+                    state = State.ERROR;
+                }
+                break;
+            case ACE:
+                currentACE.addRestrictions(node);
+                state = State.RESTRICTION;
+                break;
+            case RESTRICTION:
+                log.error("Error while reading access control content: Unexpected node: {} for state {}", node.primary, state);
+                state = State.ERROR;
+                break;
+            case ERROR:
+                // stay in error
+                break;
+        }
+        states.push(state);
+    }
+
+    public void endNode() throws SAXException {
+        State state = states.pop();
+        if (state == State.ACE) {
+            currentACE = null;
+        }
+    }
+
+    public void close() throws SAXException {
+        if (states.peek() != State.INITIAL) {
+            log.error("Unexpected end state: {}", states.peek());
+        }
+        try {
+            apply();
+        } catch (RepositoryException e) {
+            log.error("Error while applying access control content.", e);
+        }
+    }
+
+    private void apply() throws RepositoryException {
+        final String path = accessControlledNode.getPath();
+        final ValueFactory valueFactory = accessControlledNode.getSession().getValueFactory();
+
+        // find principals of existing ACL
+        JackrabbitAccessControlList acl = null;
+        Set<String> existingPrincipals = new HashSet<String>();
+        for (AccessControlPolicy p: acMgr.getPolicies(path)) {
+            if (p instanceof JackrabbitAccessControlList) {
+                acl = (JackrabbitAccessControlList) p;
+                for (AccessControlEntry ace: acl.getAccessControlEntries()) {
+                    existingPrincipals.add(ace.getPrincipal().getName());
+                }
+            }
+        }
+
+        // remove existing policy for 'overwrite'
+        if (aclHandling == AccessControlHandling.OVERWRITE && acl != null) {
+            acMgr.removePolicy(path, acl);
+            acl = null;
+        }
+
+        if (acl == null) {
+            AccessControlPolicyIterator iter = acMgr.getApplicablePolicies(path);
+            while (iter.hasNext()) {
+                AccessControlPolicy p = iter.nextAccessControlPolicy();
+                if (p instanceof JackrabbitAccessControlList) {
+                    acl = (JackrabbitAccessControlList) p;
+                    break;
+                }
+            }
+        }
+        if (acl == null) {
+            throw new RepositoryException("not JackrabbitAccessControlList applicable on " + path);
+        }
+
+        // apply ACEs of package
+        for (Map.Entry<String, List<ACE>> entry: aceMap.entrySet()) {
+            final String principalName = entry.getKey();
+            if (aclHandling == AccessControlHandling.MERGE_PRESERVE && existingPrincipals.contains(principalName)) {
+                // skip principal if it already has an ACL
+                continue;
+            }
+            Principal principal = pMgr.getPrincipal(principalName);
+            if (principal == null) {
+                principal = new Principal(){
+                    public String getName() {
+                        return principalName;
+                    }
+                };
+            }
+
+            for (ACE ace: entry.getValue()) {
+                Privilege[] privileges = new Privilege[ace.privileges.length];
+                for (int i = 0; i < privileges.length; i++) {
+                    privileges[i] = acMgr.privilegeFromName(ace.privileges[i]);
+                }
+                Map<String, Value> svRestrictions = new HashMap<String, Value>();
+                Map<String, Value[]> mvRestrictions = new HashMap<String, Value[]>();
+                for (String restName : acl.getRestrictionNames()) {
+                    DocViewProperty restriction = ace.restrictions.get(restName);
+                    if (restriction != null) {
+                        Value[] values = new Value[restriction.values.length];
+                        int type = acl.getRestrictionType(restName);
+                        for (int i=0; i<values.length; i++) {
+                            values[i] = valueFactory.createValue(restriction.values[i], type);
+                        }
+                        if (restriction.isMulti) {
+                            mvRestrictions.put(restName, values);
+                        } else {
+                            svRestrictions.put(restName, values[0]);
+                        }
+                    }
+                }
+                acl.addEntry(principal, privileges, ace.allow, svRestrictions, mvRestrictions);
+            }
+        }
+        acMgr.setPolicy(path, acl);
+    }
+
+    private static class ACE {
+
+        private final boolean allow;
+        private final String principalName;
+        private final String[] privileges;
+        private final Map<String, DocViewProperty> restrictions = new HashMap<String, DocViewProperty>();
+
+        private ACE(DocViewNode node) {
+            if ("rep:GrantACE".equals(node.primary)) {
+                allow = true;
+            } else if ("rep:DenyACE".equals(node.primary)) {
+                allow = false;
+            } else {
+                throw new IllegalArgumentException("Unexpected node ACE type: " + node.primary);
+            }
+            principalName = node.getValue("rep:principalName");
+            privileges = node.getValues("rep:privileges");
+            addRestrictions(node);
+        }
+
+        public void addRestrictions(DocViewNode node) {
+            restrictions.putAll(node.props);
+        }
+    }
+}
\ No newline at end of file

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java?rev=1560258&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java Wed Jan 22 05:49:45 2014
@@ -0,0 +1,90 @@
+/*************************************************************************
+ * 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.vault.fs.impl.io;
+
+import javax.jcr.ImportUUIDBehavior;
+import javax.jcr.Node;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.vault.util.DocViewNode;
+import org.apache.jackrabbit.vault.util.DocViewProperty;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.helpers.AttributesImpl;
+
+/**
+* {@code JcrSysViewTransformer} transforms a docview importer hierarchy to a jcr sysview one by translating the
+ * vault specific docview nodes and properties into SAX events for the JCR sysview import content handler.
+ *
+ * @see Session#getImportContentHandler(String, int)
+*/
+public class JcrSysViewTransformer implements DocViewAdapter {
+
+    /**
+     * sysview handler for special content
+     */
+    private ContentHandler handler;
+
+    JcrSysViewTransformer(Node node) throws RepositoryException, SAXException {
+        Session session = node.getSession();
+        handler = session.getImportContentHandler(
+                node.getPath(),
+                ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
+        // first define the current namespaces
+        String[] prefixes = session.getNamespacePrefixes();
+        handler.startDocument();
+        for (String prefix: prefixes) {
+            handler.startPrefixMapping(prefix, session.getNamespaceURI(prefix));
+        }
+    }
+
+    public void close() throws SAXException {
+        handler.endDocument();
+    }
+
+    public void startNode(DocViewNode ni) throws SAXException {
+        DocViewSAXImporter.log.debug("Transforming element to sysview {}", ni.name);
+
+        AttributesImpl attrs = new AttributesImpl();
+
+        attrs.addAttribute(Name.NS_SV_URI, "name", "sv:name", "CDATA", ni.name);
+        handler.startElement(Name.NS_SV_URI, "node", "sv:node", attrs);
+
+        // add the properties
+        for (DocViewProperty p: ni.props.values()) {
+            if (p != null && p.values != null) {
+                attrs = new AttributesImpl();
+                attrs.addAttribute(Name.NS_SV_URI, "name", "sv:name", "CDATA", p.name);
+                attrs.addAttribute(Name.NS_SV_URI, "type", "sv:type", "CDATA", PropertyType.nameFromValue(p.type));
+                handler.startElement(Name.NS_SV_URI, "property", "sv:property", attrs);
+                for (String v: p.values) {
+                    handler.startElement(Name.NS_SV_URI, "value", "sv:value", DocViewSAXImporter.EMPTY_ATTRIBUTES);
+                    handler.characters(v.toCharArray(), 0, v.length());
+                    handler.endElement(Name.NS_SV_URI, "value", "sv:value");
+                }
+                handler.endElement(Name.NS_SV_URI, "property", "sv:property");
+            }
+        }
+    }
+
+    public void endNode() throws SAXException {
+        handler.endElement(Name.NS_SV_URI, "node", "sv:node");
+    }
+}
\ No newline at end of file

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java?rev=1560258&r1=1560257&r2=1560258&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/io/AccessControlHandling.java Wed Jan 22 05:49:45 2014
@@ -35,19 +35,64 @@ public enum AccessControlHandling {
     OVERWRITE,
 
     /**
-     * Tries to merge access control provided with the package with the one on
-     * the target.
+     * Merge access control provided with the package with the one in the
+     * content by replacing the access control entries of corresponding
+     * principals (i.e. package first). It never alters access control entries
+     * of principals not present in the package.
+     * <p/>
+     * Example:<br/>
      *
-     * This is currently not fully supported and behaves like {@link #OVERWRITE}
-     * for existing ACLs. ACLs not in the package are retained.
+     * Content ACL:
+     * <pre>
+     *     everyone, deny, jcr:all
+     *     bob, allow, jcr:read
+     *     bob, allow, jcr:write
+     * </pre>
+     *
+     * Package ACL:
+     * <pre>
+     *     bob, deny, jcr:all
+     *     alice, allow, jcr:read
+     * </pre>
+     *
+     * Result ACL:
+     * <pre>
+     *     everyone, deny, jcr:all
+     *     bob, deny, jcr:all
+     *     alice, allow, jcr:read
+     * </pre>
      */
     MERGE,
 
     /**
-     * Tries to merge access control in the content with the one provided by the package.
+     * Merge access control in the content with the one provided with the
+     * package by adding the access control entries of principals not present in the
+     * content (i.e. content first). It never alters access control entries already
+     * existing in the content.
+     *
+     * <p/>
+     * Example:<br/>
+     *
+     * Content ACL:
+     * <pre>
+     *     everyone, deny, jcr:all
+     *     bob, allow, jcr:read
+     *     bob, allow, jcr:write
+     * </pre>
+     *
+     * Package ACL:
+     * <pre>
+     *     bob, deny, jcr:all
+     *     alice, allow, jcr:read
+     * </pre>
      *
-     * This is currently not fully supported and behaves like {@link #IGNORE}
-     * for existing ACLs. ACLs not in the package are retained.
+     * Result ACL:
+     * <pre>
+     *     everyone, deny, jcr:all
+     *     bob, allow, jcr:read
+     *     bob, allow, jcr:write
+     *     alice, allow, jcr:read
+     * </pre>
      */
     MERGE_PRESERVE,
 

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java?rev=1560258&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java Wed Jan 22 05:49:45 2014
@@ -0,0 +1,87 @@
+/*************************************************************************
+ * 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.vault.util;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.jcr.NamespaceException;
+import javax.jcr.Value;
+
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl;
+import org.apache.jackrabbit.util.ISO9075;
+import org.xml.sax.Attributes;
+
+/**
+ * Helper class that represents a (jcr) node abstraction based on
+ * {@link org.apache.jackrabbit.vault.util.DocViewProperty properties}.
+ */
+public class DocViewNode {
+
+    public final String name;
+    public final String label;
+    public final Map<String, DocViewProperty> props = new HashMap<String, DocViewProperty>();
+    public String uuid;
+    public final String[] mixins;
+    public final String primary;
+
+    public DocViewNode(String name, String label, Attributes attributes, NamePathResolver npResolver)
+            throws NamespaceException {
+        this.name = name;
+        this.label = label;
+        String uuid = null;
+        String primary = null;
+        String[] mixins = null;
+        for (int i = 0; i < attributes.getLength(); i++) {
+            // ignore non CDATA attributes
+            if (!attributes.getType(i).equals("CDATA")) {
+                continue;
+            }
+            Name pName = NameFactoryImpl.getInstance().create(
+                    attributes.getURI(i),
+                    ISO9075.decode(attributes.getLocalName(i)));
+            DocViewProperty info = DocViewProperty.parse(
+                    npResolver.getJCRName(pName),
+                    attributes.getValue(i));
+            props.put(info.name, info);
+            if (pName.equals(NameConstants.JCR_UUID)) {
+                uuid = info.values[0];
+            } else if (pName.equals(NameConstants.JCR_PRIMARYTYPE)) {
+                primary = info.values[0];
+            } else if (pName.equals(NameConstants.JCR_MIXINTYPES)) {
+                mixins = info.values;
+            }
+        }
+        this.uuid = uuid;
+        this.mixins = mixins;
+        this.primary = primary;
+    }
+
+    public String[] getValues(String name) {
+        DocViewProperty prop = props.get(name);
+        return prop == null ? null : prop.values;
+    }
+
+    public String getValue(String name) {
+        DocViewProperty prop = props.get(name);
+        return prop == null ? null : prop.values[0];
+    }
+
+}
\ No newline at end of file

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java?rev=1560258&r1=1560257&r2=1560258&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/IntegrationTestBase.java Wed Jan 22 05:49:45 2014
@@ -80,7 +80,7 @@ public class IntegrationTestBase  {
 
     @BeforeClass
     public static void initRepository() throws RepositoryException {
-        if (Boolean.getBoolean("oak")) {
+        if (isOak()) {
             Properties userProps = new Properties();
             userProps.put(UserConstants.PARAM_USER_PATH, "/home/users");
             userProps.put(UserConstants.PARAM_GROUP_PATH, "/home/groups");
@@ -128,6 +128,10 @@ public class IntegrationTestBase  {
         packMgr = new JcrPackageManagerImpl(admin);
     }
 
+    public static boolean isOak() {
+        return Boolean.getBoolean("oak");
+    }
+
     public void clean(String path) {
         try {
             admin.getNode(path).remove();

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestACLAndMerge.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestACLAndMerge.java?rev=1560258&r1=1560257&r2=1560258&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestACLAndMerge.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestACLAndMerge.java Wed Jan 22 05:49:45 2014
@@ -19,21 +19,31 @@ package org.apache.jackrabbit.vault.pack
 
 import java.io.IOException;
 import java.util.Arrays;
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 import java.util.Set;
 
 import javax.jcr.RepositoryException;
+import javax.jcr.Value;
 import javax.jcr.security.AccessControlEntry;
 import javax.jcr.security.AccessControlPolicy;
 import javax.jcr.security.Privilege;
 
+import org.apache.jackrabbit.api.JackrabbitSession;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlEntry;
 import org.apache.jackrabbit.api.security.JackrabbitAccessControlList;
+import org.apache.jackrabbit.api.security.user.Authorizable;
+import org.apache.jackrabbit.api.security.user.UserManager;
+import org.apache.jackrabbit.vault.fs.io.AccessControlHandling;
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
 import org.apache.jackrabbit.vault.packaging.JcrPackage;
 import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.junit.Assume;
 import org.junit.Test;
 
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
 /**
@@ -41,6 +51,18 @@ import static org.junit.Assert.fail;
  */
 public class TestACLAndMerge extends IntegrationTestBase {
 
+    private final static String NAME_TEST_USER = "testuser";
+
+    private UserManager uMgr;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        uMgr = ((JackrabbitSession) admin).getUserManager();
+        uMgr.createUser(NAME_TEST_USER, "test");
+        admin.save();
+    }
+
     @Override
     public void tearDown() throws Exception {
         // remove test node
@@ -48,6 +70,13 @@ public class TestACLAndMerge extends Int
             admin.getNode("/testroot").remove();
             admin.save();
         }
+        try {
+            Authorizable testUser = uMgr.getAuthorizable(NAME_TEST_USER);
+            testUser.remove();
+            admin.save();
+        } catch (RepositoryException e) {
+            // ignore
+        }
         super.tearDown();
     }
 
@@ -104,11 +133,95 @@ public class TestACLAndMerge extends Int
         assertNodeExists("/testroot/node_b");
         assertPermission("/testroot/secured", false, new String[]{"jcr:all"}, "everyone", null);
         assertPermission("/testroot/secured", true, new String[]{"jcr:read"}, "everyone", "*/foo/*");
+    }
 
+    /**
+     * Installs 2 packages with ACL for different principals. the first package has an ace for 'everyone' the 2nd for
+     * 'testuser'. the later package should not corrupt the existing acl (unlike overwrite).
+     */
+    @Test
+    public void testACMerge2() throws RepositoryException, IOException, PackageException {
+        assertNodeMissing("/testroot");
+
+        JcrPackage pack = packMgr.upload(getStream("testpackages/mode_ac_test_a.zip"), false);
+        assertNotNull(pack);
+        pack.install(getDefaultOptions());
+
+        // test if nodes and ACLs of first package exist
+        assertNodeExists("/testroot/node_a");
+        assertPermission("/testroot/secured", false, new String[]{"jcr:all"}, "everyone", null);
+
+        pack = packMgr.upload(getStream("testpackages/mode_ac_test_c_merge.zip"), false);
+        assertNotNull(pack);
+        pack.install(getDefaultOptions());
+
+        // test if nodes and ACLs of 2nd package exist
+        assertNodeExists("/testroot/node_a");
+        assertNodeExists("/testroot/node_c");
+        assertPermission("/testroot/secured", false, new String[]{"jcr:all"}, "everyone", null);
+        assertPermission("/testroot/secured", true, new String[]{"jcr:all"}, "testuser", null);
     }
 
     /**
-     * Installs 2 packages with the same ACL. the later packages has AC Handling MERGE_PRESERVER and should
+     * Installs 2 packages with ACL for different principals. the first package has an ace for 'everyone' the 2nd for
+     * 'everyone' and 'testuser'. merge mode should overwrite the 'everyone' ACE.
+     */
+    @Test
+    public void testACMerge3() throws RepositoryException, IOException, PackageException {
+        assertNodeMissing("/testroot");
+
+        JcrPackage pack = packMgr.upload(getStream("testpackages/mode_ac_test_a.zip"), false);
+        assertNotNull(pack);
+        pack.install(getDefaultOptions());
+
+        // test if nodes and ACLs of first package exist
+        assertNodeExists("/testroot/node_a");
+        assertPermission("/testroot/secured", false, new String[]{"jcr:all"}, "everyone", null);
+
+        pack = packMgr.upload(getStream("testpackages/mode_ac_test_d.zip"), false);
+        assertNotNull(pack);
+        pack.install(getDefaultOptions());
+
+        // test if nodes and ACLs of 2nd package exist
+        assertNodeExists("/testroot/node_a");
+        assertNodeExists("/testroot/node_d");
+        assertPermission("/testroot/secured", true, new String[]{"jcr:all"}, "everyone", null);
+        assertPermission("/testroot/secured", true, new String[]{"jcr:all"}, "testuser", null);
+    }
+
+    /**
+     * Installs 2 packages with ACL for different principals. the first package has an ace for 'everyone' the 2nd for
+     * 'everyone' and 'testuser'. merge_preserve mode should NOT overwrite the 'everyone' ACE.
+     */
+    @Test
+    public void testACMergePreserve2() throws RepositoryException, IOException, PackageException {
+        assertNodeMissing("/testroot");
+
+        JcrPackage pack = packMgr.upload(getStream("testpackages/mode_ac_test_a.zip"), false);
+        assertNotNull(pack);
+        pack.install(getDefaultOptions());
+
+        // test if nodes and ACLs of first package exist
+        assertNodeExists("/testroot/node_a");
+        assertPermission("/testroot/secured", false, new String[]{"jcr:all"}, "everyone", null);
+
+        pack = packMgr.upload(getStream("testpackages/mode_ac_test_d.zip"), false);
+        assertNotNull(pack);
+        ImportOptions opts = getDefaultOptions();
+        opts.setAccessControlHandling(AccessControlHandling.MERGE_PRESERVE);
+        pack.install(opts);
+
+        // test if nodes and ACLs of 2nd package exist
+        assertNodeExists("/testroot/node_a");
+        assertNodeExists("/testroot/node_d");
+        assertPermission("/testroot/secured", false, new String[]{"jcr:all"}, "everyone", null);
+        assertPermission("/testroot/secured", true, new String[]{"jcr:all"}, "testuser", null);
+    }
+
+
+
+    /**
+     * Installs 2 packages with the same ACL. the later packages has AC Handling MERGE_PRESERVE and should
      * retain the existing ACL.
      */
     @Test
@@ -135,21 +248,53 @@ public class TestACLAndMerge extends Int
 
     }
 
+    /**
+     * Installs a package with oak ACL content.
+     */
+    @Test
+    public void testOakContent() throws RepositoryException, IOException, PackageException {
+        Assume.assumeTrue(isOak());
+        assertNodeMissing("/testroot");
+
+        JcrPackage pack = packMgr.upload(getStream("testpackages/oak_ac_content_test.zip"), false);
+        assertNotNull(pack);
+        pack.install(getDefaultOptions());
+
+        // test if nodes and ACLs of first package exist
+        assertNodeExists("/testroot/node_a");
+        Map<String, String[]> restrictions = new HashMap<String, String[]>();
+        restrictions.put("rep:glob", new String[]{"*/foo"});
+        restrictions.put("rep:ntNames", new String[]{"nt:unstructured"});
+        restrictions.put("rep:prefixes", new String[]{"rep", "granite"});
+        assertTrue(
+                "expected permission missing",
+                hasPermission("/testroot/secured", true, new String[]{"jcr:all"}, "everyone", restrictions)
+        );
+    }
+
     protected void assertPermissionMissing(String path, boolean allow, String[] privs, String name, String globRest)
             throws RepositoryException {
-        if (hasPermission(path, allow, privs, name, globRest)) {
+        Map<String, String[]> restrictions = new HashMap<String, String[]>();
+        if (globRest != null) {
+            restrictions.put("rep:glob", new String[]{globRest});
+        }
+        if (hasPermission(path, allow, privs, name, restrictions)) {
             fail("Expected permission should not exist on path " + path);
         }
     }
 
     protected void assertPermission(String path, boolean allow, String[] privs, String name, String globRest)
             throws RepositoryException {
-        if (!hasPermission(path, allow, privs, name, globRest)) {
+        Map<String, String[]> restrictions = new HashMap<String, String[]>();
+        if (globRest != null) {
+            restrictions.put("rep:glob", new String[]{globRest});
+        }
+        if (!hasPermission(path, allow, privs, name, restrictions)) {
             fail("Expected permission missing on path " + path);
         }
     }
 
-    protected boolean hasPermission(String path, boolean allow, String[] privs, String name, String globRest)
+    protected boolean hasPermission(String path, boolean allow, String[] privs, String name, Map<String, String[]> restrictions)
             throws RepositoryException {
         AccessControlPolicy[] ap = admin.getAccessControlManager().getPolicies(path);
         boolean found = false;
@@ -175,7 +320,31 @@ public class TestACLAndMerge extends Int
                         if (!expectedPrivs.isEmpty()) {
                             continue;
                         }
-                        if (globRest != null && !globRest.equals(ace.getRestriction("rep:glob").getString())) {
+                        Map<String, String[]> rests = new HashMap<String, String[]>(restrictions);
+                        boolean restrictionExpected = true;
+                        for (String restName: ace.getRestrictionNames()) {
+                            String[] expected = rests.remove(restName);
+                            if (expected == null) {
+                                continue;
+                            }
+                            Value[] values;
+                            if ("rep:glob".equals(restName)) {
+                                values = new Value[]{ace.getRestriction(restName)};
+                            } else {
+                                values = ace.getRestrictions(restName);
+                            }
+                            String[] actual = new String[values.length];
+                            for (int i=0; i<actual.length; i++) {
+                                actual[i] = values[i].getString();
+                            }
+                            Arrays.sort(expected);
+                            Arrays.sort(actual);
+                            if (!Arrays.equals(expected, actual)) {
+                                restrictionExpected = false;
+                                break;
+                            }
+                        }
+                        if (!restrictionExpected || !rests.isEmpty()) {
                             continue;
                         }
                         found = true;

Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/mode_ac_test_c_merge.zip
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/mode_ac_test_c_merge.zip?rev=1560258&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/mode_ac_test_c_merge.zip
------------------------------------------------------------------------------
    svn:mime-type = application/jar

Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/mode_ac_test_d.zip
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/mode_ac_test_d.zip?rev=1560258&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/mode_ac_test_d.zip
------------------------------------------------------------------------------
    svn:mime-type = application/jar

Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/oak_ac_content_test.zip
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/oak_ac_content_test.zip?rev=1560258&view=auto
==============================================================================
Binary file - no diff available.

Propchange: jackrabbit/commons/filevault/trunk/vault-core/src/test/resources/org/apache/jackrabbit/vault/packaging/integration/testpackages/oak_ac_content_test.zip
------------------------------------------------------------------------------
    svn:mime-type = application/jar