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 2018/06/21 03:52:06 UTC

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

Author: tripod
Date: Thu Jun 21 03:52:06 2018
New Revision: 1833974

URL: http://svn.apache.org/viewvc?rev=1833974&view=rev
Log:
JCRVLT-303 Register namespace under a unique prefix in case of clash

Added:
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNamespaceHelper.java
    jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNamespaceImport.java
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/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java
    jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.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=1833974&r1=1833973&r2=1833974&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 Thu Jun 21 03:52:06 2018
@@ -62,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.fs.spi.impl.jcr20.JcrNamespaceHelper;
 import org.apache.jackrabbit.vault.util.DocViewNode;
 import org.apache.jackrabbit.vault.util.DocViewProperty;
 import org.apache.jackrabbit.vault.util.JcrConstants;
@@ -225,6 +226,11 @@ public class DocViewSAXImporter extends
     private final boolean snsSupported;
 
     /**
+     * helper for namespace registration
+     */
+    private final JcrNamespaceHelper nsHelper;
+
+    /**
      * Creates a new importer that will receive SAX events and imports the
      * items below the given root.
      *
@@ -247,6 +253,7 @@ public class DocViewSAXImporter extends
         this.userManagement = ServiceProviderFactory.getProvider().getUserManagement();
         this.snsSupported = session.getRepository().
                 getDescriptorValue(Repository.NODE_TYPE_MANAGEMENT_SAME_NAME_SIBLINGS_SUPPORTED).getBoolean();
+        this.nsHelper = new JcrNamespaceHelper(session, null);
 
         String rootPath = parentNode.getPath();
         if (!rootPath.equals("/")) {
@@ -506,11 +513,10 @@ public class DocViewSAXImporter extends
         } catch (NamespaceException e) {
             // assume uri never registered
             try {
-                session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
+                oldPrefix = nsHelper.registerNamespace(prefix, uri);
             } catch (RepositoryException e1) {
                 throw new SAXException(e);
             }
-            oldPrefix = prefix;
         } catch (RepositoryException e) {
             throw new SAXException(e);
         }

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java?rev=1833974&r1=1833973&r2=1833974&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JackrabbitPrivilegeInstaller.java Thu Jun 21 03:52:06 2018
@@ -21,7 +21,6 @@ import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -73,21 +72,10 @@ public class JackrabbitPrivilegeInstalle
             mode = tracker.setMode(ProgressTrackerListener.Mode.TEXT);
         }
 
+        JcrNamespaceHelper nsHelper = new JcrNamespaceHelper(session, tracker);
+
         // register namespaces
-        Map<String, String> pfxToURI = defs.getNamespaceMapping().getPrefixToURIMapping();
-        if (!pfxToURI.isEmpty()) {
-            for (Object o : pfxToURI.keySet()) {
-                String prefix = (String) o;
-                String uri = pfxToURI.get(prefix);
-                try {
-                    session.getNamespacePrefix(uri);
-                    track(tracker, "-", prefix + " -> " + uri);
-                } catch (RepositoryException e) {
-                    session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
-                    track(tracker, "A", prefix + " -> " + uri);
-                }
-            }
-        }
+        nsHelper.registerNamespaces(defs.getNamespaceMapping().getPrefixToURIMapping());
 
         // register node types
         List<Privilege> registeredPrivs = new LinkedList<Privilege>();

Added: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNamespaceHelper.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNamespaceHelper.java?rev=1833974&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNamespaceHelper.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNamespaceHelper.java Thu Jun 21 03:52:06 2018
@@ -0,0 +1,99 @@
+/*
+ * 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.spi.impl.jcr20;
+
+import java.util.Map;
+
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+import javax.jcr.NamespaceException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+
+import org.apache.jackrabbit.vault.fs.spi.ProgressTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class JcrNamespaceHelper {
+
+    /**
+     * default logger
+     */
+    private static final Logger log = LoggerFactory.getLogger(JcrNamespaceHelper.class);
+
+    private final Session session;
+
+    private final ProgressTracker tracker;
+
+    public JcrNamespaceHelper(@Nonnull Session session, @Nullable ProgressTracker tracker) {
+        this.session = session;
+        this.tracker = tracker;
+    }
+
+    /**
+     * Registers a map of namespaces
+     * @param pfxToURI map from prefix to uri mappings
+     * @throws RepositoryException if an error occurs
+     */
+    public void registerNamespaces(@Nonnull Map<String, String> pfxToURI) throws RepositoryException {
+        if (!pfxToURI.isEmpty()) {
+            for (Object o : pfxToURI.keySet()) {
+                String prefix = (String) o;
+                String uri = pfxToURI.get(prefix);
+                try {
+                    session.getNamespacePrefix(uri);
+                    track(tracker, "-", prefix + " -> " + uri);
+                } catch (RepositoryException e) {
+                    registerNamespace(prefix, uri);
+                }
+            }
+        }
+    }
+
+    /**
+     * Attempts to register a namespace
+     * @param pfxHint prefix to use if possible
+     * @param uri uri to register
+     * @return the registered prefix
+     * @throws RepositoryException if an error occurs
+     */
+    @Nonnull
+    public String registerNamespace(@Nonnull String pfxHint, @Nonnull String uri) throws RepositoryException {
+        int i = 0;
+        String pfx = pfxHint;
+        Throwable error = null;
+        while (i < 1000) {
+            try {
+                session.getWorkspace().getNamespaceRegistry().registerNamespace(pfx, uri);
+                track(tracker, "A", pfx + " -> " + uri);
+                return pfx;
+            } catch (NamespaceException e) {
+                pfx = pfxHint + i++;
+                error = e;
+            }
+        }
+        throw new RepositoryException("Giving up automatic namespace registration after 1000 attempts.", error);
+    }
+
+    private void track(ProgressTracker tracker, String action, String path) {
+        log.debug("{} {}", action, path);
+        if (tracker != null) {
+            tracker.track(action, path);
+        }
+    }
+}

Modified: jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.java?rev=1833974&r1=1833973&r2=1833974&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/main/java/org/apache/jackrabbit/vault/fs/spi/impl/jcr20/JcrNodeTypeInstaller.java Thu Jun 21 03:52:06 2018
@@ -21,7 +21,6 @@ import java.io.IOException;
 import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
-import java.util.Map;
 
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
@@ -67,6 +66,8 @@ public class JcrNodeTypeInstaller implem
         // register node types
         NodeTypeManager ntMgr = session.getWorkspace().getNodeTypeManager();
 
+        JcrNamespaceHelper nsHelper = new JcrNamespaceHelper(session, tracker);
+
         // filter out registered
         DefaultNodeTypeSet set;
         if (types instanceof DefaultNodeTypeSet) {
@@ -88,20 +89,7 @@ public class JcrNodeTypeInstaller implem
         }
 
         // register namespaces
-        Map<String, String> pfxToURI = set.getNamespaceMapping().getPrefixToURIMapping();
-        if (!pfxToURI.isEmpty()) {
-            for (Object o : pfxToURI.keySet()) {
-                String prefix = (String) o;
-                String uri = (String) pfxToURI.get(prefix);
-                try {
-                    session.getNamespacePrefix(uri);
-                    track(tracker, "-", prefix + " -> " + uri);
-                } catch (RepositoryException e) {
-                    session.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
-                    track(tracker, "A", prefix + " -> " + uri);
-                }
-            }
-        }
+        nsHelper.registerNamespaces(set.getNamespaceMapping().getPrefixToURIMapping());
 
         // register node types
         NodeTypeDefinitionFactory fac = new NodeTypeDefinitionFactory(session);

Added: jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNamespaceImport.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNamespaceImport.java?rev=1833974&view=auto
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNamespaceImport.java (added)
+++ jackrabbit/commons/filevault/trunk/vault-core/src/test/java/org/apache/jackrabbit/vault/packaging/integration/TestNamespaceImport.java Thu Jun 21 03:52:06 2018
@@ -0,0 +1,170 @@
+/*
+ * 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.packaging.integration;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.jcr.Node;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+
+import org.apache.jackrabbit.oak.jcr.Jcr;
+import org.apache.jackrabbit.vault.fs.api.PathFilterSet;
+import org.apache.jackrabbit.vault.fs.config.DefaultMetaInf;
+import org.apache.jackrabbit.vault.fs.config.DefaultWorkspaceFilter;
+import org.apache.jackrabbit.vault.fs.io.Archive;
+import org.apache.jackrabbit.vault.fs.io.ImportOptions;
+import org.apache.jackrabbit.vault.packaging.ExportOptions;
+import org.apache.jackrabbit.vault.packaging.PackageException;
+import org.apache.jackrabbit.vault.packaging.VaultPackage;
+import org.apache.jackrabbit.vault.packaging.impl.JcrPackageManagerImpl;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotEquals;
+
+public class TestNamespaceImport {
+
+    private final static String PREFIX = "prefix";
+
+    private final static String URI1 = "http://one.namespace.io";
+
+    private final static String URI2 = "http://two.namespace.io";
+
+    private Instance i1;
+
+    private Instance i2;
+
+    @Before
+    public void setup() throws RepositoryException {
+        i1 = new Instance();
+        i2 = new Instance();
+
+        // Register namespaces with same prefix but different URIs
+        // on different instances, i1, i2
+        i1.registerNamespace(PREFIX, URI1);
+        i2.registerNamespace(PREFIX, URI2);
+    }
+
+    @Test
+    public void importClashingNamespace() throws RepositoryException, IOException, PackageException {
+
+        // Set a property with the namespace prefix on instance i1
+        i1.getRootNode().addNode("tmp").setProperty("{" + URI1 + "}prop1", "value1");
+        i1.admin.save();
+
+        // Export the property from instance i1 in a content package archive
+
+        ExportOptions opts = new ExportOptions();
+        DefaultMetaInf inf = new DefaultMetaInf();
+        DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
+        filter.add(new PathFilterSet("/tmp"));
+        inf.setFilter(filter);
+        Properties props = new Properties();
+        props.setProperty(VaultPackage.NAME_GROUP, "jackrabbit/test");
+        props.setProperty(VaultPackage.NAME_NAME, "test-package");
+        inf.setProperties(props);
+        opts.setMetaInf(inf);
+
+        File tmpFile = File.createTempFile("vaulttest", "zip");
+        VaultPackage pkg = i1.packMgr.assemble(i1.admin, opts, tmpFile);
+        Archive archive = pkg.getArchive();
+
+        // Import the archive in the instance i2, with strict mode enabled
+
+        ImportOptions io = new ImportOptions();
+        io.setStrict(true);
+        i2.packMgr.extract(archive, io, true);
+
+        assertEquals(i2.getRootNode().getNode("tmp").getProperty("{" + URI1 + "}prop1").getString(), "value1");
+
+    }
+
+    @Test
+    public void importClashingNamespaceOnPath() throws RepositoryException, IOException, PackageException {
+
+        // Set a property with the namespace prefix on instance i1
+        i1.getRootNode().addNode("tmp").addNode("{" + URI1 + "}node1").setProperty("test", "value1");
+        i1.admin.save();
+
+        // Export the property from instance i1 in a content package archive
+
+        ExportOptions opts = new ExportOptions();
+        DefaultMetaInf inf = new DefaultMetaInf();
+        DefaultWorkspaceFilter filter = new DefaultWorkspaceFilter();
+        filter.add(new PathFilterSet("/tmp"));
+        inf.setFilter(filter);
+        Properties props = new Properties();
+        props.setProperty(VaultPackage.NAME_GROUP, "jackrabbit/test");
+        props.setProperty(VaultPackage.NAME_NAME, "test-package");
+        inf.setProperties(props);
+        opts.setMetaInf(inf);
+
+        File tmpFile = File.createTempFile("vaulttest", "zip");
+        VaultPackage pkg = i1.packMgr.assemble(i1.admin, opts, tmpFile);
+        Archive archive = pkg.getArchive();
+
+        // Import the archive in the instance i2, with strict mode enabled
+
+        ImportOptions io = new ImportOptions();
+        io.setStrict(true);
+        i2.packMgr.extract(archive, io, true);
+
+        assertEquals(i2.getRootNode().getProperty("tmp/{" + URI1 + "}node1/test").getString(), "value1");
+
+        i2.relogin();
+        assertNotEquals(PREFIX, i2.admin.getNamespacePrefix(URI1));
+    }
+
+    private static final class Instance {
+
+        final Repository repository;
+
+        Session admin;
+
+        final JcrPackageManagerImpl packMgr;
+
+        private Instance()
+                throws RepositoryException {
+            repository = new Jcr().createRepository();
+            admin = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
+            packMgr = new JcrPackageManagerImpl(admin, new String[0]);
+        }
+
+        Node getRootNode()
+                throws RepositoryException {
+            return admin.getRootNode();
+        }
+
+        void registerNamespace(String prefix, String uri)
+                throws RepositoryException {
+            admin.getWorkspace().getNamespaceRegistry().registerNamespace(prefix, uri);
+        }
+
+        void relogin() throws RepositoryException {
+            admin.logout();
+            admin = repository.login(new SimpleCredentials("admin", "admin".toCharArray()));
+
+        }
+    }
+
+}