You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@chemistry.apache.org by md...@apache.org on 2012/08/30 12:10:32 UTC

svn commit: r1378875 - in /chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr: JcrConverter.java JcrNode.java JcrRepository.java

Author: mduerig
Date: Thu Aug 30 10:10:32 2012
New Revision: 1378875

URL: http://svn.apache.org/viewvc?rev=1378875&view=rev
Log:
CMIS-563: JcrConverter.setProperty escaping issues
 applied slightly edited patch. Thanks Ivan Vasiliev for the patch

Modified:
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrConverter.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrNode.java
    chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrRepository.java

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrConverter.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrConverter.java?rev=1378875&r1=1378874&r2=1378875&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrConverter.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrConverter.java Thu Aug 30 10:10:32 2012
@@ -19,6 +19,25 @@
 
 package org.apache.chemistry.opencmis.jcr;
 
+import java.math.BigDecimal;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.NodeType;
+
 import org.apache.chemistry.opencmis.commons.PropertyIds;
 import org.apache.chemistry.opencmis.commons.data.PropertyBoolean;
 import org.apache.chemistry.opencmis.commons.data.PropertyData;
@@ -38,30 +57,23 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyStringImpl;
 import org.apache.chemistry.opencmis.commons.impl.dataobjects.PropertyUriImpl;
 import org.apache.chemistry.opencmis.jcr.util.Util;
-
-import javax.jcr.Node;
-import javax.jcr.Property;
-import javax.jcr.PropertyType;
-import javax.jcr.RepositoryException;
-import javax.jcr.Value;
-import javax.jcr.ValueFactory;
-import javax.jcr.ValueFormatException;
-import javax.jcr.nodetype.NodeType;
-import java.math.BigDecimal;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.GregorianCalendar;
-import java.util.List;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 /**
  * Utility class providing methods for converting various entities from/to their respective representation
  * in JCR/CMIS.
  */
 public final class JcrConverter {
+
+    private static final Logger log = LoggerFactory.getLogger(JcrConverter.class);
+    private static final Pattern QUALIFIED_NAME = Pattern.compile("\\{([^}]*)\\}(.*)");
+    private static final Pattern PREFIXED_NAME = Pattern.compile("(([^:/]+):)?([^:]*)");
+    
     private JcrConverter() {}
 
     /**
-     * Escapes all illegal JCR name characters of a string.
+     * Escapes all illegal for JCR local name characters of a string.
      * The encoding is loosely modeled after URI encoding, but only encodes
      * the characters it absolutely needs to in order to make the resulting
      * string a valid JCR name.
@@ -79,9 +91,9 @@ public final class JcrConverter {
      *
      * @param cmisName the name to escape
      * @return the escaped name
-     */    
-    public static String toJcrName(String cmisName) {
-        StringBuilder buffer = new StringBuilder(cmisName.length() * 2);
+     */
+    private static String escapeForJcr(String cmisName){
+        StringBuilder buffer = new StringBuilder(cmisName.length() * 16 + 32);
         for (int i = 0; i < cmisName.length(); i++) {
             char ch = cmisName.charAt(i);
             if (ch == '%' || ch == '/' || ch == ':' || ch == '[' || ch == ']' || ch == '*' || ch == '|'
@@ -100,27 +112,52 @@ public final class JcrConverter {
     }
 
     /**
-     * Checks if the given name is valid a valid JCR name
-     *
-     * @param name  the name to check
-     * @return <code>true</code> if the name is valid, <code>false</code> otherwise.
-     */
-    public static boolean isValidJcrName(String name) { 
-        if (name == null || name.length() == 0) {
-            return false;
+     * See JSR-283, 3.2 Names
+     * A JCR name is an ordered pair of strings:
+     * (N, L) where N is a JCR namespace and L is a JCR local name.
+     * @param cmisName the name to escape
+     * @return the escaped name
+     */    
+    public static String toJcrName(String cmisName) {
+        if (cmisName == null || cmisName.length()==0){
+            return null;
         }
-
-        for (int i = 0; i < name.length(); i++) {
-            char ch = name.charAt(i);
-            if (ch == '%' || ch == '/' || ch == ':' || ch == '[' || ch == ']' || ch == '*' || ch == '|'
-                    || ch == '\t' || ch == '\r' || ch == '\n'
-                    || ch == '.' && name.length() < 3
-                    || ch == ' ' && (i == 0 || i == name.length() - 1)) {
-                return false;
+        if (cmisName.charAt(0) == '{') {
+            Matcher matcher = QUALIFIED_NAME.matcher(cmisName);
+            if (matcher.matches()) {
+                String namespaceUri = matcher.group(1);
+                String localName = matcher.group(2);
+                StringBuilder builder = new StringBuilder(cmisName.length() * 16 + 32);
+                if (namespaceUri != null && namespaceUri.length() > 0) {
+                    //This must be valid URI
+                    try {
+                        namespaceUri = new URI(namespaceUri).toString();
+                        builder.append('{');
+                        builder.append(namespaceUri);
+                        builder.append('}');
+                    } catch (URISyntaxException e1) {
+                        //Skip URI
+                        log.debug(e1.getMessage(),e1);
+                    }
+                }
+                builder.append(escapeForJcr(localName));
+                return builder.toString();
+            }
+        } else {
+            Matcher matcher = PREFIXED_NAME.matcher(cmisName);
+            if (matcher.matches()) {
+                String prefix = matcher.group(2);
+                String localName = matcher.group(3);
+                StringBuilder builder = new StringBuilder(cmisName.length() * 16 + 32);
+                if (prefix != null && prefix.length() > 0) {
+                    builder.append(escapeForJcr(prefix));
+                    builder.append(':');
+                }
+                builder.append(escapeForJcr(localName));
+                return builder.toString();
             }
         }
-
-        return true;
+        return escapeForJcr(cmisName);
     }
 
     /**

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrNode.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrNode.java?rev=1378875&r1=1378874&r2=1378875&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrNode.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrNode.java Thu Aug 30 10:10:32 2012
@@ -19,6 +19,24 @@
 
 package org.apache.chemistry.opencmis.jcr;
 
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.version.Version;
+import javax.jcr.version.VersionHistory;
+import javax.jcr.version.VersionManager;
+
 import org.apache.chemistry.opencmis.commons.PropertyIds;
 import org.apache.chemistry.opencmis.commons.data.AllowableActions;
 import org.apache.chemistry.opencmis.commons.data.ObjectData;
@@ -32,7 +50,6 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.enums.Updatability;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
-import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisRuntimeException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisStorageException;
@@ -52,23 +69,6 @@ import org.apache.chemistry.opencmis.jcr
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.Node;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.Property;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.version.Version;
-import javax.jcr.version.VersionHistory;
-import javax.jcr.version.VersionManager;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-
 /**
  * Common base class for all JCR <code>Node</code>s to be represented as CMIS objects. Instances of this class
  * are responsible for mapping from CMIS to JCR and vice versa.
@@ -319,15 +319,11 @@ public abstract class JcrNode {
      */
     public JcrNode updateProperties(Properties properties) {
         // get and check the new name
-        String newName = PropertyHelper.getStringProperty(properties, PropertyIds.NAME);
+        String newName = JcrConverter.toJcrName(PropertyHelper.getStringProperty(properties, PropertyIds.NAME));
         boolean rename = newName != null && !getName().equals(newName);
-        if (rename && !JcrConverter.isValidJcrName(newName)) {
-            throw new CmisNameConstraintViolationException("Name is not valid: " + newName);
-        }
         if (rename && isRoot()) {
             throw new CmisUpdateConflictException("Cannot rename root node");
         }
-
         try {
             // rename file or folder if necessary
             Session session = getNode().getSession();

Modified: chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrRepository.java
URL: http://svn.apache.org/viewvc/chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrRepository.java?rev=1378875&r1=1378874&r2=1378875&view=diff
==============================================================================
--- chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrRepository.java (original)
+++ chemistry/opencmis/trunk/chemistry-opencmis-server/chemistry-opencmis-server-jcr/src/main/java/org/apache/chemistry/opencmis/jcr/JcrRepository.java Thu Aug 30 10:10:32 2012
@@ -18,6 +18,28 @@
  */
 package org.apache.chemistry.opencmis.jcr;
 
+import java.math.BigInteger;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+import javax.jcr.Credentials;
+import javax.jcr.ItemNotFoundException;
+import javax.jcr.LoginException;
+import javax.jcr.NoSuchWorkspaceException;
+import javax.jcr.Node;
+import javax.jcr.NodeIterator;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.Repository;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.query.Query;
+import javax.jcr.query.QueryManager;
+import javax.jcr.query.QueryResult;
+
 import org.apache.chemistry.opencmis.commons.PropertyIds;
 import org.apache.chemistry.opencmis.commons.data.AllowableActions;
 import org.apache.chemistry.opencmis.commons.data.ContentStream;
@@ -42,7 +64,6 @@ import org.apache.chemistry.opencmis.com
 import org.apache.chemistry.opencmis.commons.enums.VersioningState;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException;
-import org.apache.chemistry.opencmis.commons.exceptions.CmisNameConstraintViolationException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisNotSupportedException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException;
 import org.apache.chemistry.opencmis.commons.exceptions.CmisPermissionDeniedException;
@@ -65,27 +86,6 @@ import org.apache.chemistry.opencmis.jcr
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import javax.jcr.Credentials;
-import javax.jcr.ItemNotFoundException;
-import javax.jcr.LoginException;
-import javax.jcr.NoSuchWorkspaceException;
-import javax.jcr.Node;
-import javax.jcr.NodeIterator;
-import javax.jcr.PathNotFoundException;
-import javax.jcr.Repository;
-import javax.jcr.RepositoryException;
-import javax.jcr.Session;
-import javax.jcr.query.Query;
-import javax.jcr.query.QueryManager;
-import javax.jcr.query.QueryResult;
-import java.math.BigInteger;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-
 /**
  * JCR back-end for CMIS server.
  */
@@ -230,16 +230,12 @@ public class JcrRepository {
             throw new CmisConstraintException("Versioning required for " + typeId);
         }
 
-        // check the name
+        // get the name
         String name = PropertyHelper.getStringProperty(properties, PropertyIds.NAME);
-        if (!JcrConverter.isValidJcrName(name)) {
-            throw new CmisNameConstraintViolationException("Name is not valid: " + name);
-        }
-
         // get parent Node and create child
         JcrFolder parent = getJcrNode(session, folderId).asFolder();
         JcrDocumentTypeHandler typeHandler = typeHandlerManager.getDocumentTypeHandler(typeId);
-        JcrNode jcrNode = typeHandler.createDocument(parent, name, properties, contentStream, versioningState);
+        JcrNode jcrNode = typeHandler.createDocument(parent, JcrConverter.toJcrName(name), properties, contentStream, versioningState);
         return jcrNode.getId();
     }
 
@@ -289,16 +285,12 @@ public class JcrRepository {
             throw new CmisObjectNotFoundException("Type '" + typeId + "' is unknown!");
         }
 
-        // check the name
+        // get the name
         String name = PropertyHelper.getStringProperty(properties, PropertyIds.NAME);
-        if (!JcrConverter.isValidJcrName(name)) {
-            throw new CmisNameConstraintViolationException("Name is not valid: " + name);
-        }
-
         // get parent Node
         JcrFolder parent = getJcrNode(session, folderId).asFolder();
         JcrFolderTypeHandler typeHandler = typeHandlerManager.getFolderTypeHandler(typeId);
-        JcrNode jcrNode = typeHandler.createFolder(parent, name, properties);
+        JcrNode jcrNode = typeHandler.createFolder(parent, JcrConverter.toJcrName(name), properties);
         return jcrNode.getId();
     }