You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by kw...@apache.org on 2020/02/13 11:36:09 UTC

svn commit: r1873974 - in /jackrabbit/commons/filevault/trunk/vault-validation/src: main/java/org/apache/jackrabbit/vault/validation/impl/util/ main/java/org/apache/jackrabbit/vault/validation/spi/ test/java/org/apache/jackrabbit/vault/validation/ test...

Author: kwin
Date: Thu Feb 13 11:36:09 2020
New Revision: 1873974

URL: http://svn.apache.org/viewvc?rev=1873974&view=rev
Log:
JCRVLT-409 emit node names in expanded form

Modified:
    jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/impl/util/DocumentViewXmlContentHandler.java
    jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/DocumentViewXmlValidator.java
    jackrabbit/commons/filevault/trunk/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/DocumentViewParserValidatorTest.java
    jackrabbit/commons/filevault/trunk/vault-validation/src/test/resources/simple-package/jcr_root/apps/.content.xml

Modified: jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/impl/util/DocumentViewXmlContentHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/impl/util/DocumentViewXmlContentHandler.java?rev=1873974&r1=1873973&r2=1873974&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/impl/util/DocumentViewXmlContentHandler.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/impl/util/DocumentViewXmlContentHandler.java Thu Feb 13 11:36:09 2020
@@ -25,9 +25,15 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import javax.jcr.NamespaceException;
+import javax.xml.namespace.QName;
+
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
+import org.apache.jackrabbit.spi.commons.conversion.NameParser;
 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.util.Text;
 import org.apache.jackrabbit.vault.util.DocViewNode;
@@ -43,7 +49,7 @@ import org.xml.sax.SAXException;
 import org.xml.sax.helpers.DefaultHandler;
 
 /** TODO: reuse more logic from DocViewSAXImporter (https://issues.apache.org/jira/browse/JCRVLT-357) */
-public class DocumentViewXmlContentHandler extends DefaultHandler {
+public class DocumentViewXmlContentHandler extends DefaultHandler implements NamespaceResolver {
 
     private final @NotNull Map<String, Integer> nodePathsAndLineNumbers;
     private String rootNodeName;
@@ -54,6 +60,7 @@ public class DocumentViewXmlContentHandl
     private Deque<DocViewNode> nodeStack;
     private Deque<String> nodePathStack;
     private final Map<String, DocumentViewXmlValidator> validators;
+    private final Map<String, String> namespaceRegistry;
 
     private @NotNull List<ValidationViolation> violations;
 
@@ -96,31 +103,76 @@ public class DocumentViewXmlContentHandl
         nodePathStack = new LinkedList<>();
         this.validators = documentViewXmlValidators;
         violations = new LinkedList<>();
+        namespaceRegistry = new HashMap<>();
     }
 
+    
     @Override
-    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
-        // convert to DocViewNode (mostly taken over from DocViewSAXImporter#startElement)
-        String label = ISO9075.decode(qName);
-        if (elementNameStack.isEmpty()) {
-            if (localName.equals(NameConstants.JCR_ROOT.getLocalName())
-                    && uri.equals(NameConstants.JCR_ROOT.getNamespaceURI())) {
-                // take over node name from file name
-                label = rootNodeName;
-            } else {
-                // element name takes precedence over file name
-                rootNodeName = label;
-            }
+    public void startPrefixMapping(String prefix, String uri) throws SAXException {
+        namespaceRegistry.put(prefix, uri);
+    }
+
+
+    @Override
+    public void endPrefixMapping(String prefix) throws SAXException {
+        namespaceRegistry.remove(prefix);
+    }
+
+    
+    @Override
+    public String getPrefix(String uri) throws NamespaceException {
+        throw new UnsupportedOperationException("Only resolving from prefix to URI is supported, but not vice-versa");
+    }
+
+
+    @Override
+    public String getURI(String prefix) throws NamespaceException {
+        if (prefix.isEmpty()) {
+            return Name.NS_DEFAULT_URI;
         }
+        return namespaceRegistry.get(prefix);
+    }
 
-        String name = label; // name is usually the same except for SNS nodes
 
+    private Name getExpandedName(String name) throws IllegalNameException, NamespaceException {
+        return NameParser.parse(name, this, NameFactoryImpl.getInstance());
+    }
+
+    /**
+     * Resolves the ISO-9075 encoding and removes a same-name sibling suffix from the name which is either a localName or qualified name
+     * @param name
+     * @return the normalized name
+     */
+    private String getNormalizedName(String name) {
         // in the case of SNS nodes the name contains an index in brackets as suffix
+        name = ISO9075.decode(name);
         int idx = name.lastIndexOf('[');
         if (idx > 0) {
             name = name.substring(0, idx);
         }
-        elementNameStack.push(name);
+        return name;
+    }
+
+    @Override
+    public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException {
+        // convert to DocViewNode (mostly taken over from DocViewSAXImporter#startElement)
+        String label = qName;
+        Name name;
+        if (elementNameStack.isEmpty() && localName.equals(NameConstants.JCR_ROOT.getLocalName())
+                    && uri.equals(NameConstants.JCR_ROOT.getNamespaceURI())) {
+                // take over node name from file name
+                label = rootNodeName;
+                try {
+                    name = getExpandedName(rootNodeName);
+                } catch (IllegalNameException|NamespaceException e) {
+                    throw new SAXException("Given root node name (implicitly given via filename) cannot be resolved. The prefix used in the filename must be defined in the XML as well!", e);
+                }
+        } else {
+            name = NameFactoryImpl.getInstance().create(uri, getNormalizedName(localName));
+        }
+
+        // the path is being given via the qualified (prefixed) names
+        elementNameStack.push(label);
 
         // add fully qualified name
         StringBuilder nodePath = new StringBuilder(rootNodeParentPath);
@@ -129,8 +181,9 @@ public class DocumentViewXmlContentHandl
             nodePath.append("/").append(iterator.next());
         }
         nodePathStack.push(nodePath.toString());
+        
         try {
-            DocViewNode node = getDocViewNode(name, label, attributes);
+            DocViewNode node = getDocViewNode(name, qName, attributes);
             nodeStack.push(node);
             violations.add(new ValidationViolation(ValidationMessageSeverity.DEBUG, "Validate node '" + node + "' start"));
             for (Map.Entry<String, DocumentViewXmlValidator> entry : validators.entrySet()) {
@@ -153,7 +206,7 @@ public class DocumentViewXmlContentHandl
         }
     }
 
-    private DocViewNode getDocViewNode(String name, String label, Attributes attributes) {
+    private DocViewNode getDocViewNode(Name name, String label, Attributes attributes) {
         Map<String, DocViewProperty> propertyMap = new HashMap<>();
         
         String uuid = null;
@@ -173,8 +226,7 @@ public class DocumentViewXmlContentHandl
                 mixins = property.values;
             }
         }
-        
-        return new DocViewNode(name, label, uuid, propertyMap, mixins, primary);
+        return new DocViewNode(name.toString(), label, uuid, propertyMap, mixins, primary);
     }
 
     /** @return a Collection of absolute node paths (i.e. starting with "/") with "/" as path delimiter. */

Modified: jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/DocumentViewXmlValidator.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/DocumentViewXmlValidator.java?rev=1873974&r1=1873973&r2=1873974&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/DocumentViewXmlValidator.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-validation/src/main/java/org/apache/jackrabbit/vault/validation/spi/DocumentViewXmlValidator.java Thu Feb 13 11:36:09 2020
@@ -20,7 +20,9 @@ import java.nio.file.Path;
 import java.util.Collection;
 
 import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
 import org.apache.jackrabbit.vault.util.DocViewNode;
+import org.apache.jackrabbit.vault.validation.spi.util.NameUtil;
 import org.jetbrains.annotations.NotNull;
 import org.jetbrains.annotations.Nullable;
 import org.osgi.annotation.versioning.ProviderType;
@@ -37,10 +39,11 @@ public interface DocumentViewXmlValidato
     /**
      * Called for the beginning of each new JCR document view node.
      * Deserialization of the node information was already done when this method is called!
-     * The attribute names have the string representation outlined in {@link Name} (i.e. including the expanded namespace uri in the format <code>{namespaceURI}localPart</code>).
+     * The node and attribute names have the string representation outlined in {@link Name} (i.e. including the namespace uri in the format <code>{namespaceURI}localPart</code>).
      * This is also referred to as <a href="https://docs.adobe.com/docs/en/spec/jcr/2.0/3_Repository_Model.html#3.2.5.1%20Expanded%20Form">JCR name expanded form</a>.
      * To construct such names either use {@link NameUtil} or use the constants from {@link NameConstants}.
      * 
+     * The node's label refers to the XML element name specifying the node. There shouldn't be any checks derived from it, but only from the expanded name.
      * @param node the node which should be validated
      * @param nodePath the absolute repository path of the given node
      * @param filePath the relative file path of the docview file containing this node

Modified: jackrabbit/commons/filevault/trunk/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/DocumentViewParserValidatorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/DocumentViewParserValidatorTest.java?rev=1873974&r1=1873973&r2=1873974&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/DocumentViewParserValidatorTest.java (original)
+++ jackrabbit/commons/filevault/trunk/vault-validation/src/test/java/org/apache/jackrabbit/vault/validation/DocumentViewParserValidatorTest.java Thu Feb 13 11:36:09 2020
@@ -83,21 +83,24 @@ public class DocumentViewParserValidator
             Collection<ValidationMessage> messages = validator.validateJcrData(input, Paths.get("apps", ".content.xml"), nodePathsAndLineNumbers);
             // filter
             ValidationExecutorTest.assertViolation(messages,
-                    new ValidationViolation("docviewid", ValidationMessageSeverity.ERROR, "startDocView", Paths.get("apps/.content.xml"), Paths.get(""), "/apps", 19, 36, null
+                    new ValidationViolation("docviewid", ValidationMessageSeverity.ERROR, "startDocView", Paths.get("apps/.content.xml"), Paths.get(""), "/apps", 19, 35, null
                             ),
                     new ValidationViolation("docviewid", ValidationMessageSeverity.ERROR,
-                            "startDocView", Paths.get("apps/.content.xml"), Paths.get(""), "/apps/somepath", 22, 6, null));
+                            "startDocView", Paths.get("apps/.content.xml"), Paths.get(""), "/apps/somepath", 21, 29, null),
+                    new ValidationViolation("docviewid", ValidationMessageSeverity.ERROR,
+                            "startDocView", Paths.get("apps/.content.xml"), Paths.get(""), "/apps/somepath/jc:content", 22, 54, null));
 
             // verify node names
             Map<String, Integer> expectedNodePathsAndLineNumber = new HashMap<>();
             expectedNodePathsAndLineNumber.put("/apps", 19);
-            expectedNodePathsAndLineNumber.put("/apps/somepath", 22);
+            expectedNodePathsAndLineNumber.put("/apps/somepath", 21);
+            expectedNodePathsAndLineNumber.put("/apps/somepath/jc:content", 22);
             Assert.assertEquals(expectedNodePathsAndLineNumber, nodePathsAndLineNumbers);
             Map<String, DocViewProperty> properties = new HashMap<>();
             properties.put(NameConstants.JCR_PRIMARYTYPE.toString(),
                     new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(), new String[] { "sling:Folder" }, false,
                             PropertyType.UNDEFINED));
-            DocViewNode node = new DocViewNode("apps", "apps", null, properties, null, "sling:Folder");
+            DocViewNode node = new DocViewNode("{}apps", "jc:root", null, properties, null, "sling:Folder");
             Mockito.verify(docViewXmlValidator).validate(node, "/apps", Paths.get("apps", ".content.xml"), true);
 
             properties = new HashMap<>();
@@ -105,8 +108,15 @@ public class DocumentViewParserValidator
                     new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(), new String[] { JcrConstants.NT_UNSTRUCTURED }, false,
                             PropertyType.UNDEFINED));
             properties.put("{}attribute1", new DocViewProperty("{}attribute1", new String[] { "value1" }, false, PropertyType.UNDEFINED));
-            node = new DocViewNode("somepath", "somepath", null, properties, null, JcrConstants.NT_UNSTRUCTURED);
+            node = new DocViewNode("{}somepath", "somepath", null, properties, null, JcrConstants.NT_UNSTRUCTURED);
             Mockito.verify(docViewXmlValidator).validate(node, "/apps/somepath", Paths.get("apps", ".content.xml"), false);
+            
+            properties = new HashMap<>();
+            properties.put(NameConstants.JCR_PRIMARYTYPE.toString(),
+                    new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(), new String[] { JcrConstants.NT_UNSTRUCTURED }, false,
+                            PropertyType.UNDEFINED));
+            node = new DocViewNode("{http://www.jcp.org/jcr/1.0}content", "jc:content", null, properties, null, JcrConstants.NT_UNSTRUCTURED);
+            Mockito.verify(docViewXmlValidator).validate(node, "/apps/somepath/jc:content", Paths.get("apps", ".content.xml"), false);
         }
     }
 
@@ -136,7 +146,7 @@ public class DocumentViewParserValidator
             properties.put(NameConstants.JCR_PRIMARYTYPE.toString(),
                     new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(), new String[] { "sling:Folder" }, false,
                             PropertyType.UNDEFINED));
-            DocViewNode node = new DocViewNode("child1", "child1", null, properties, null, "sling:Folder");
+            DocViewNode node = new DocViewNode("{}child1", "jcr:root", null, properties, null, "sling:Folder");
             Mockito.verify(docViewXmlValidator).validate(node, "/apps/child1", Paths.get("apps", "child1.xml"), true);
 
             properties = new HashMap<>();
@@ -144,7 +154,7 @@ public class DocumentViewParserValidator
                     new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(), new String[] { JcrConstants.NT_UNSTRUCTURED }, false,
                             PropertyType.UNDEFINED));
             properties.put("{}attribute1", new DocViewProperty("{}attribute1", new String[] { "value1" }, false, PropertyType.UNDEFINED));
-            node = new DocViewNode("somepath", "somepath", null, properties, null, JcrConstants.NT_UNSTRUCTURED);
+            node = new DocViewNode("{}somepath", "somepath", null, properties, null, JcrConstants.NT_UNSTRUCTURED);
             Mockito.verify(docViewXmlValidator).validate(node, "/apps/child1/somepath", Paths.get("apps", "child1.xml"), false);
 
             // verify node names
@@ -166,7 +176,7 @@ public class DocumentViewParserValidator
             properties.put(NameConstants.JCR_PRIMARYTYPE.toString(),
                     new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(), new String[] { "sling:Folder" }, false,
                             PropertyType.UNDEFINED));
-            DocViewNode node = new DocViewNode("child3", "child3", null, properties, null, "sling:Folder");
+            DocViewNode node = new DocViewNode("{}child3", "child3", null, properties, null, "sling:Folder");
             Mockito.verify(docViewXmlValidator).validate(node, "/apps/child3", Paths.get("apps", "child2", ".content.xml"), true);
 
             properties = new HashMap<>();
@@ -174,7 +184,7 @@ public class DocumentViewParserValidator
                     new DocViewProperty(NameConstants.JCR_PRIMARYTYPE.toString(), new String[] { JcrConstants.NT_UNSTRUCTURED }, false,
                             PropertyType.UNDEFINED));
             properties.put("{}attribute1", new DocViewProperty("{}attribute1", new String[] { "value1" }, false, PropertyType.UNDEFINED));
-            node = new DocViewNode("somepath", "somepath", null, properties, null, JcrConstants.NT_UNSTRUCTURED);
+            node = new DocViewNode("{}somepath", "somepath", null, properties, null, JcrConstants.NT_UNSTRUCTURED);
             Mockito.verify(docViewXmlValidator).validate(node, "/apps/child3/somepath", Paths.get("apps", "child2", ".content.xml"), false);
 
             // verify node names

Modified: jackrabbit/commons/filevault/trunk/vault-validation/src/test/resources/simple-package/jcr_root/apps/.content.xml
URL: http://svn.apache.org/viewvc/jackrabbit/commons/filevault/trunk/vault-validation/src/test/resources/simple-package/jcr_root/apps/.content.xml?rev=1873974&r1=1873973&r2=1873974&view=diff
==============================================================================
--- jackrabbit/commons/filevault/trunk/vault-validation/src/test/resources/simple-package/jcr_root/apps/.content.xml (original)
+++ jackrabbit/commons/filevault/trunk/vault-validation/src/test/resources/simple-package/jcr_root/apps/.content.xml Thu Feb 13 11:36:09 2020
@@ -15,9 +15,11 @@
   See the License for the specific language governing permissions and
   limitations under the License.
   -->
-<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
-    jcr:primaryType="sling:Folder">
-    <somepath jcr:primaryType="nt:unstructured"
-        attribute1="value1"
-    ></somepath>
-</jcr:root>
+<jc:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jc="http://www.jcp.org/jcr/1.0"
+    jc:primaryType="sling:Folder">
+    <somepath jc:primaryType="nt:unstructured"
+        attribute1="value1">
+        <jc:content jc:primaryType="nt:unstructured">
+        </jc:content>
+    </somepath>
+</jc:root>