You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by an...@apache.org on 2010/03/10 11:17:46 UTC

svn commit: r921283 - in /jackrabbit/trunk: jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/ jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/ jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/ jackrabbit-spi2...

Author: angela
Date: Wed Mar 10 10:17:45 2010
New Revision: 921283

URL: http://svn.apache.org/viewvc?rev=921283&view=rev
Log:
JCR-2553 : Batch fails to create/modify properties with non-ascii characters names

Added:
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/BinaryPart.java   (with props)
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/StringPart.java   (with props)
    jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/CreateFileTest.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java
    jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/AbstractSPITest.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java
    jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/TestAll.java

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java?rev=921283&r1=921282&r2=921283&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/HttpMultipartPost.java Wed Mar 10 10:17:45 2010
@@ -79,10 +79,17 @@ class HttpMultipartPost {
         }
 
         ServletFileUpload upload = new ServletFileUpload(getFileItemFactory(tmpDir));
+        // make sure the content disposition headers are read with the charset
+        // specified in the request content type (or UTF-8 if no charset is specified).
+        // see JCR
+        if (request.getCharacterEncoding() == null) {
+            upload.setHeaderEncoding("UTF-8");
+        }
         try {
-            List<Object> fileItems = upload.parseRequest(request);
-            for (Object fileItem : fileItems) {
-                addItem((FileItem) fileItem);
+            @SuppressWarnings("unchecked")
+            List<FileItem> fileItems = upload.parseRequest(request);
+            for (FileItem fileItem : fileItems) {
+                addItem(fileItem);
             }
         } catch (FileUploadException e) {
             log.error("Error while processing multipart.", e);

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java?rev=921283&r1=921282&r2=921283&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/util/RequestData.java Wed Mar 10 10:17:45 2010
@@ -16,13 +16,10 @@
  */
 package org.apache.jackrabbit.server.util;
 
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 import javax.servlet.http.HttpServletRequest;
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.File;
 import java.util.HashSet;
 import java.util.Iterator;
 
@@ -31,11 +28,6 @@ import java.util.Iterator;
  */
 public class RequestData {
 
-    /**
-     * logger instance
-     */
-    private static final Logger log = LoggerFactory.getLogger(RequestData.class);
-
     private final HttpServletRequest request;
     private final HttpMultipartPost mpReq;
 
@@ -57,7 +49,7 @@ public class RequestData {
      * @return an iterator over strings.
      */
     public Iterator<String> getParameterNames() {
-        
+        @SuppressWarnings("unchecked")
         HashSet<String> names = new HashSet<String>(request.getParameterMap().keySet());
         names.addAll(mpReq.getParameterNames());
         

Modified: jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/AbstractSPITest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/AbstractSPITest.java?rev=921283&r1=921282&r2=921283&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/AbstractSPITest.java (original)
+++ jackrabbit/trunk/jackrabbit-spi/src/test/java/org/apache/jackrabbit/spi/AbstractSPITest.java Wed Mar 10 10:17:45 2010
@@ -89,11 +89,13 @@ public class AbstractSPITest extends Tes
         return helper.getProperty(RepositoryServiceStub.PROP_PREFIX + "." + propName);
     }
 
+    @Override
     protected void setUp() throws Exception {
         super.setUp();
         sessionInfo = helper.getAdminSessionInfo();
     }
 
+    @Override
     protected void tearDown() throws Exception {
         if (sessionInfo != null) {
             helper.getRepositoryService().dispose(sessionInfo);

Added: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/BinaryPart.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/BinaryPart.java?rev=921283&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/BinaryPart.java (added)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/BinaryPart.java Wed Mar 10 10:17:45 2010
@@ -0,0 +1,53 @@
+/*
+ * 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.spi2davex;
+
+import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.PartSource;
+import org.apache.commons.httpclient.util.EncodingUtil;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * <code>BinaryPart</code> extends from the default HttpClient 3.x
+ * FilePart and sends the name/filename in the Content Disposition header
+ * with the specified charset.
+ *
+ * TODO: This class can be removed once we upgrade to HttpClient 4.x (JCR-2406)
+ */
+class BinaryPart extends FilePart {
+
+    public BinaryPart(String name, PartSource partSource, String contentType, String charset) {
+        super(name, partSource, contentType, charset);
+    }
+
+    @Override
+    protected void sendDispositionHeader(OutputStream out) throws IOException {
+        out.write(CONTENT_DISPOSITION_BYTES);
+        out.write(QUOTE_BYTES);
+        out.write(EncodingUtil.getBytes(getName(), getCharSet()));
+        out.write(QUOTE_BYTES);
+        String filename = getSource().getFileName();
+        if (filename != null) {
+            out.write(EncodingUtil.getAsciiBytes(FILE_NAME));
+            out.write(QUOTE_BYTES);
+            out.write(EncodingUtil.getBytes(getName(), getCharSet()));
+            out.write(QUOTE_BYTES);
+        }
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/BinaryPart.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/BinaryPart.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java?rev=921283&r1=921282&r2=921283&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/RepositoryServiceImpl.java Wed Mar 10 10:17:45 2010
@@ -33,11 +33,9 @@ import org.apache.commons.httpclient.Htt
 import org.apache.commons.httpclient.HttpException;
 import org.apache.commons.httpclient.HttpMethod;
 import org.apache.commons.httpclient.methods.RequestEntity;
-import org.apache.commons.httpclient.methods.multipart.FilePart;
 import org.apache.commons.httpclient.methods.multipart.MultipartRequestEntity;
 import org.apache.commons.httpclient.methods.multipart.Part;
 import org.apache.commons.httpclient.methods.multipart.PartBase;
-import org.apache.commons.httpclient.methods.multipart.StringPart;
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.commons.json.JsonParser;
 import org.apache.jackrabbit.commons.json.JsonUtil;
@@ -734,7 +732,7 @@ public class RepositoryServiceImpl exten
             Part part;
             switch (value.getType()) {
                 case PropertyType.BINARY:
-                    part = new FilePart(paramName, new BinaryPartSource(value));
+                    part = new BinaryPart(paramName, new BinaryPartSource(value), JcrValueType.contentTypeFromType(PropertyType.BINARY), DEFAULT_CHARSET);
                     break;
                 case PropertyType.NAME:
                     part = new StringPart(paramName, resolver.getJCRName(value.getName()), DEFAULT_CHARSET);

Added: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/StringPart.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/StringPart.java?rev=921283&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/StringPart.java (added)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/StringPart.java Wed Mar 10 10:17:45 2010
@@ -0,0 +1,46 @@
+/*
+ * 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.spi2davex;
+
+import org.apache.commons.httpclient.util.EncodingUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.OutputStream;
+
+/**
+ * <code>StringPart</code> extending from the default HttpClient 3.x
+ * StringPart and sending the name in the Content Disposition header
+ * with the specified charset.
+ *
+ * TODO: This class can be removed once we upgrade to HttpClient 4.x (JCR-2406)
+ */
+class StringPart extends org.apache.commons.httpclient.methods.multipart.StringPart {
+
+    public StringPart(String name, String value, String charset) {
+        super(name, value, charset);
+    }
+
+    @Override
+    protected void sendDispositionHeader(OutputStream out) throws IOException {
+        out.write(CONTENT_DISPOSITION_BYTES);
+        out.write(QUOTE_BYTES);
+        out.write(EncodingUtil.getBytes(getName(), getCharSet()));
+        out.write(QUOTE_BYTES);
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/StringPart.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi2dav/src/main/java/org/apache/jackrabbit/spi2davex/StringPart.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/CreateFileTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/CreateFileTest.java?rev=921283&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/CreateFileTest.java (added)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/CreateFileTest.java Wed Mar 10 10:17:45 2010
@@ -0,0 +1,153 @@
+/*
+ * 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.spi2davex;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+
+import javax.jcr.NamespaceException;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.jackrabbit.JcrConstants;
+import org.apache.jackrabbit.spi.AbstractSPITest;
+import org.apache.jackrabbit.spi.Batch;
+import org.apache.jackrabbit.spi.Name;
+import org.apache.jackrabbit.spi.NodeId;
+import org.apache.jackrabbit.spi.PropertyInfo;
+import org.apache.jackrabbit.spi.QValue;
+import org.apache.jackrabbit.spi.RepositoryService;
+import org.apache.jackrabbit.spi.SessionInfo;
+import org.apache.jackrabbit.spi.commons.conversion.DefaultNamePathResolver;
+import org.apache.jackrabbit.spi.commons.conversion.IllegalNameException;
+import org.apache.jackrabbit.spi.commons.conversion.NamePathResolver;
+import org.apache.jackrabbit.spi.commons.name.NameConstants;
+import org.apache.jackrabbit.spi.commons.namespace.AbstractNamespaceResolver;
+import org.apache.jackrabbit.spi.commons.namespace.NamespaceResolver;
+
+/**
+ * <code>CreateFileTest</code>...
+ */
+public class CreateFileTest extends AbstractSPITest {
+    
+    private final String testPath = "/test";
+    private NamePathResolver resolver;
+    private RepositoryService rs;
+    private SessionInfo si;
+
+    private QValue lastModified;
+    private QValue mimeType;
+    private QValue enc;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        rs = helper.getRepositoryService();
+        si = helper.getAdminSessionInfo();
+        NamespaceResolver nsResolver = new AbstractNamespaceResolver() {
+            public String getURI(String prefix) {
+                return ("jcr".equals(prefix)) ? "http://www.jcp.org/jcr/1.0" : prefix;
+            }
+            public String getPrefix(String uri) {
+                return ("http://www.jcp.org/jcr/1.0".equals(uri)) ? "jcr" : uri;
+            }
+        };
+        resolver = new DefaultNamePathResolver(nsResolver);
+
+        try {
+            rs.getNodeInfo(si, getNodeId(testPath));
+        } catch (RepositoryException e) {
+            Batch b = rs.createBatch(si, getNodeId("/"));
+            b.addNode(getNodeId("/"), resolver.getQName("test"), NameConstants.NT_UNSTRUCTURED, null);
+            rs.submit(b);
+        }
+
+        lastModified = rs.getQValueFactory().create(Calendar.getInstance());
+        mimeType = rs.getQValueFactory().create("text/plain", PropertyType.STRING);
+        enc = rs.getQValueFactory().create("utf-8", PropertyType.STRING);
+    }
+
+    @Override
+    protected void tearDown() throws Exception {
+        try {
+            Batch b = rs.createBatch(si, getNodeId("/"));
+            b.remove(getNodeId(testPath));
+            rs.submit(b);
+        } finally {
+            rs.dispose(si);
+            super.tearDown();
+        }
+    }
+
+    private NodeId getNodeId(String path) throws RepositoryException {
+        return rs.getIdFactory().createNodeId((String) null,
+                resolver.getQPath(path));
+    }
+
+    public void testCreateFile() throws RepositoryException, IOException {
+        Name fileName = resolver.getQName("test.txt");
+        createFile(fileName);
+    }
+
+    public void testCreateFileWithNonLatinCharacters() throws RepositoryException, IOException {
+        Name fileName = resolver.getQName("\u0633\u0634.txt");
+        createFile(fileName);
+    }
+
+    public void testPropertiesWithNonLatinCharacters() throws RepositoryException, IOException {
+        Name fileName = resolver.getQName("\u0633\u0634.txt");
+        createFile(fileName);
+
+        NodeId nid = getNodeId(testPath + "/\u0633\u0634.txt/jcr:content");
+
+        PropertyInfo pi = rs.getPropertyInfo(si, rs.getIdFactory().createPropertyId(nid, NameConstants.JCR_LASTMODIFIED));
+        assertEquals(lastModified, pi.getValues()[0]);
+
+        pi = rs.getPropertyInfo(si, rs.getIdFactory().createPropertyId(nid, NameConstants.JCR_MIMETYPE));
+        assertEquals(mimeType, pi.getValues()[0]);
+
+        pi = rs.getPropertyInfo(si, rs.getIdFactory().createPropertyId(nid, NameConstants.JCR_ENCODING));
+        assertEquals(enc, pi.getValues()[0]);
+
+        pi = rs.getPropertyInfo(si, rs.getIdFactory().createPropertyId(nid, NameConstants.JCR_DATA));
+        assertEquals("\u0633\u0634", pi.getValues()[0].getString());
+    }
+
+    private void createFile(Name fileName) throws RepositoryException, IOException {
+        NodeId root = getNodeId(testPath);
+
+        Batch b = rs.createBatch(si, root);
+        b.addNode(root, fileName, NameConstants.NT_FILE, null);
+
+        String filePath = testPath + "/" + fileName.getLocalName();
+        NodeId file = getNodeId(filePath);
+        b.addNode(file, NameConstants.JCR_CONTENT, NameConstants.NT_RESOURCE, null);
+
+        NodeId content = getNodeId(filePath + "/" + NameConstants.JCR_CONTENT);
+        b.addProperty(content, resolver.getQName(JcrConstants.JCR_LASTMODIFIED), lastModified);
+        b.addProperty(content, resolver.getQName(JcrConstants.JCR_MIMETYPE), mimeType);
+        b.addProperty(content, resolver.getQName(JcrConstants.JCR_ENCODING), enc);
+
+        InputStream data = new ByteArrayInputStream("\u0633\u0634".getBytes("UTF-8"));
+        b.addProperty(content, resolver.getQName(JcrConstants.JCR_DATA), rs.getQValueFactory().create(data));
+
+        rs.submit(b);
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/CreateFileTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/CreateFileTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/TestAll.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/TestAll.java?rev=921283&r1=921282&r2=921283&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/TestAll.java (original)
+++ jackrabbit/trunk/jackrabbit-spi2dav/src/test/java/org/apache/jackrabbit/spi2davex/TestAll.java Wed Mar 10 10:17:45 2010
@@ -36,6 +36,7 @@ public class TestAll extends TestCase {
         suite.addTestSuite(CopyTest.class);
         suite.addTestSuite(CloneTest.class);
         suite.addTestSuite(ExtensionTest.class);
+        suite.addTestSuite(CreateFileTest.class);
 
         return suite;
     }