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/10/28 01:28:32 UTC

svn commit: r1634753 - in /jackrabbit/commons/filevault/trunk/vault-core/src: main/java/org/apache/jackrabbit/vault/fs/impl/io/ main/java/org/apache/jackrabbit/vault/util/ test/java/org/apache/jackrabbit/vault/packaging/integration/

Author: tripod
Date: Tue Oct 28 00:28:32 2014
New Revision: 1634753

URL: http://svn.apache.org/r1634753
Log:
JCRVLT-66 Updating an exiting authorizable does not work if on different path (mode=merge)
JCRVLT-67 rep:authorizableId might be removed on package install causing error in oak

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/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/java/org/apache/jackrabbit/vault/packaging/integration/TestUserContentPackage.java

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=1634753&r1=1634752&r2=1634753&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 Tue Oct 28 00:28:32 2014
@@ -635,37 +635,7 @@ public class DocViewSAXImporter extends 
                                 stack = stack.push();
                             }
                         } else if (userManagement != null && userManagement.isAuthorizableNodeType(ni.primary)) {
-                            boolean skip = false;
-                            String id = userManagement.getAuthorizableId(ni);
-                            String oldPath = node.getPath() + "/" + ni.name;
-                            if (wspFilter.getImportMode(oldPath) == ImportMode.MERGE) {
-                                String existingPath = userManagement.getAuthorizablePath(this.session, id);
-                                if (existingPath != null) {
-                                    // if existing path is not the same as this, we need to register this so that further
-                                    // nodes down the line (i.e. profiles, policies) are imported at the correct location
-                                    if (!oldPath.equals(existingPath)) {
-                                        importInfo.onRemapped(oldPath, existingPath);
-                                    }
-                                    skip = true;
-
-                                    // remember desired memberships. todo: how to deal with multi-node memberships?
-                                    DocViewProperty prop = ni.props.get("rep:members");
-                                    if (prop != null) {
-                                        importInfo.registerMemberships(id, prop.values);
-                                    }
-                                }
-                            }
-                            if (skip) {
-                                log.info("Skipping import of existing authorizable '{}' due to MERGE import mode.", id);
-                                stack = stack.push();
-                                importInfo.onNop(node.getPath() + "/" + ni.name);
-                            } else {
-                                log.debug("Authorizable element detected. starting sysview transformation {}/{}", node.getPath(), name);
-                                stack = stack.push();
-                                stack.adapter = new JcrSysViewTransformer(node);
-                                stack.adapter.startNode(ni);
-                                importInfo.onCreated(node.getPath() + "/" + ni.name);
-                            }
+                            handleAuthorizable(node, ni);
                         } else {
                             stack = stack.push(addNode(ni));
                         }
@@ -686,6 +656,90 @@ public class DocViewSAXImporter extends 
         }
     }
 
+    /**
+     * Handle an authorizable node
+     * @param node the parent node
+     * @param ni doc view node of the authorizable
+     * @throws RepositoryException
+     * @throws SAXException
+     */
+    private void handleAuthorizable(Node node, DocViewNode ni) throws RepositoryException, SAXException {
+        String id = userManagement.getAuthorizableId(ni);
+        String newPath = node.getPath() + "/" + ni.name;
+        String oldPath = userManagement.getAuthorizablePath(this.session, id);
+        if (oldPath == null) {
+            // just import the authorizable node
+            log.debug("Authorizable element detected. starting sysview transformation {}", newPath);
+            stack = stack.push();
+            stack.adapter = new JcrSysViewTransformer(node);
+            stack.adapter.startNode(ni);
+            importInfo.onCreated(newPath);
+            return;
+        }
+
+        Node authNode = session.getNode(oldPath);
+        ImportMode mode = wspFilter.getImportMode(oldPath);
+        // if existing path is not the same as this, we need to register this so that further
+        // nodes down the line (i.e. profiles, policies) are imported at the correct location
+        // todo: check if this also works cross-aggregates
+        if (mode != ImportMode.REPLACE && !oldPath.equals(newPath)) {
+            importInfo.onRemapped(oldPath, newPath);
+        }
+
+        switch (mode) {
+            case MERGE:
+                // remember desired memberships.
+                // todo: how to deal with multi-node memberships? see JCRVLT-69
+                DocViewProperty prop = ni.props.get("rep:members");
+                if (prop != null) {
+                    importInfo.registerMemberships(id, prop.values);
+                }
+
+                log.info("Skipping import of existing authorizable '{}' due to MERGE import mode.", id);
+                stack = stack.push(new StackElement(authNode, false));
+                importInfo.onNop(oldPath);
+                break;
+
+            case REPLACE:
+                // just replace the entire subtree for now.
+                log.debug("Authorizable element detected. starting sysview transformation {}", newPath);
+                stack = stack.push();
+                stack.adapter = new JcrSysViewTransformer(node);
+                stack.adapter.startNode(ni);
+                importInfo.onReplaced(newPath);
+                break;
+
+            case UPDATE:
+                log.debug("Authorizable element detected. starting sysview transformation {}", newPath);
+                stack = stack.push();
+                stack.adapter = new JcrSysViewTransformer(node, oldPath);
+                // we need to tweak the ni.name so that the sysview import does not
+                // rename the authorizable node name
+                String newName = Text.getName(oldPath);
+                DocViewNode mapped = new DocViewNode(
+                        newName,
+                        newName,
+                        ni.uuid,
+                        ni.props,
+                        ni.mixins,
+                        ni.primary
+                );
+                // but we need to be augment with a potential rep:authorizableId
+                if (authNode.hasProperty("rep:authorizableId")) {
+                    DocViewProperty authId = new DocViewProperty(
+                            "rep:authorizableId",
+                            new String[]{authNode.getProperty("rep:authorizableId").getString()},
+                            false,
+                            PropertyType.STRING
+                    );
+                    mapped.props.put(authId.name, authId);
+                }
+                stack.adapter.startNode(mapped);
+                importInfo.onReplaced(newPath);
+                break;
+        }
+    }
+
     private StackElement addNode(DocViewNode ni) throws RepositoryException, IOException {
         final Node currentNode = stack.getNode();
 

Modified: 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=1634753&r1=1634752&r2=1634753&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/impl/io/JcrSysViewTransformer.java Tue Oct 28 00:28:32 2014
@@ -18,6 +18,7 @@ package org.apache.jackrabbit.vault.fs.i
 
 import javax.jcr.ImportUUIDBehavior;
 import javax.jcr.Node;
+import javax.jcr.NodeIterator;
 import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -25,6 +26,9 @@ 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.apache.jackrabbit.vault.util.JcrConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 import org.xml.sax.ContentHandler;
 import org.xml.sax.SAXException;
 import org.xml.sax.helpers.AttributesImpl;
@@ -38,25 +42,91 @@ import org.xml.sax.helpers.AttributesImp
 public class JcrSysViewTransformer implements DocViewAdapter {
 
     /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(JcrSysViewTransformer.class);
+
+    /**
      * sysview handler for special content
      */
     private ContentHandler handler;
 
-    JcrSysViewTransformer(Node node) throws RepositoryException, SAXException {
+    /**
+     * temporary node when 'rescuing' the child nodes
+     */
+    private Node tmpNode;
+
+    private final String existingPath;
+
+    public JcrSysViewTransformer(Node node) throws SAXException, RepositoryException {
+        this(node, null);
+    }
+
+    JcrSysViewTransformer(Node node, String existingPath) throws RepositoryException, SAXException {
         Session session = node.getSession();
         handler = session.getImportContentHandler(
                 node.getPath(),
-                ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING);
+                existingPath != null
+                        ? ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING
+                        : 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));
         }
+
+        this.existingPath = existingPath;
+        if (existingPath != null) {
+            Node existingNode = session.getNode(existingPath);
+            // check if there is an existing node with the name
+            try {
+                // if old node exist, try to 'save' the child nodes
+                NodeIterator iter = existingNode.getNodes();
+                while (iter.hasNext()) {
+                    Node child = iter.nextNode();
+                    if (tmpNode == null) {
+                        tmpNode = session.getRootNode().addNode("tmp" + System.currentTimeMillis(), JcrConstants.NT_UNSTRUCTURED);
+                    }
+                    try {
+                        session.move(child.getPath(), tmpNode.getPath() + "/" + child.getName());
+                    } catch (RepositoryException e) {
+                        log.error("Error while moving child node to temporary location. Child will be removed.", e);
+                    }
+                }
+            } catch (RepositoryException e) {
+                log.warn("error while moving child nodes (ignored)", e);
+            }
+        }
     }
 
     public void close() throws SAXException {
         handler.endDocument();
+
+        // check for rescued child nodes
+        // move the old child nodes back
+        if (tmpNode != null) {
+            try {
+                Session session = tmpNode.getSession();
+                Node node = session.getNode(existingPath);
+                NodeIterator iter = tmpNode.getNodes();
+                while (iter.hasNext()) {
+                    Node child = iter.nextNode();
+                    String newPath = node.getPath() + "/" + child.getName();
+                    try {
+                        session.move(child.getPath(), newPath);
+                    } catch (RepositoryException e) {
+                        log.warn("Unable to move child back to new location at {} due to: {}. Node will remain in temporary location: {}",
+                                new Object[]{newPath, e.getMessage(), child.getPath()});
+                    }
+                }
+                tmpNode.remove();
+            } catch (RepositoryException e) {
+                log.error("Error while processing rescued child nodes");
+            }
+        }
+
     }
 
     public void startNode(DocViewNode ni) throws SAXException {

Modified: 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=1634753&r1=1634752&r2=1634753&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/util/DocViewNode.java Tue Oct 28 00:28:32 2014
@@ -42,6 +42,15 @@ public class DocViewNode {
     public final String[] mixins;
     public final String primary;
 
+    public DocViewNode(String name, String label, String uuid, Map<String, DocViewProperty> props, String[] mixins, String primary) {
+        this.name = name;
+        this.label = label;
+        this.uuid = uuid;
+        this.mixins = mixins;
+        this.primary = primary;
+        this.props.putAll(props);
+    }
+
     public DocViewNode(String name, String label, Attributes attributes, NamePathResolver npResolver)
             throws NamespaceException {
         this.name = name;

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestUserContentPackage.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestUserContentPackage.java?rev=1634753&r1=1634752&r2=1634753&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestUserContentPackage.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestUserContentPackage.java Tue Oct 28 00:28:32 2014
@@ -78,25 +78,21 @@ public class TestUserContentPackage exte
     }
 
     @Test
-    @Ignore("JCRVLT-66")
     public void installUserA_Merge() throws RepositoryException, IOException, PackageException {
         installUserA(ImportMode.MERGE, false, false);
     }
 
     @Test
-    @Ignore("JCRVLT-66")
     public void installUserA_Merge_PkgPath() throws RepositoryException, IOException, PackageException {
         installUserA(ImportMode.MERGE, true, true);
     }
 
     @Test
-    @Ignore("JCRVLT-66")
     public void installUserA_Update() throws RepositoryException, IOException, PackageException {
         installUserA(ImportMode.UPDATE, false, false);
     }
 
     @Test
-    @Ignore("JCRVLT-66")
     public void installUserA_Update_PkgPath() throws RepositoryException, IOException, PackageException {
         installUserA(ImportMode.UPDATE, true, true);
     }