You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by cz...@apache.org on 2010/12/30 13:50:20 UTC

svn commit: r1053879 - in /sling/trunk/bundles/jcr/resource/src: main/java/org/apache/sling/jcr/resource/internal/helper/jcr/ test/java/org/apache/sling/jcr/resource/internal/helper/jcr/

Author: cziegeler
Date: Thu Dec 30 12:50:20 2010
New Revision: 1053879

URL: http://svn.apache.org/viewvc?rev=1053879&view=rev
Log:
SLING-1761 : JcrPropertyResource sets incorrect content length for strings containing non-ascii character
Applied slightly modified patch from Julian Sedding

Added:
    sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java   (with props)
Modified:
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
    sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java
    sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java
    sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java?rev=1053879&r1=1053878&r2=1053879&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResource.java Thu Dec 30 12:50:20 2010
@@ -18,9 +18,12 @@
  */
 package org.apache.sling.jcr.resource.internal.helper.jcr;
 
+import java.io.UnsupportedEncodingException;
 import java.util.Iterator;
 
 import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 
 import org.apache.sling.api.resource.AbstractResource;
@@ -28,9 +31,16 @@ import org.apache.sling.api.resource.Res
 import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.resource.ResourceResolver;
 import org.apache.sling.jcr.resource.JcrResourceConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 abstract class JcrItemResource extends AbstractResource implements Resource {
 
+    /**
+     * default log
+     */
+    private static final Logger LOGGER = LoggerFactory.getLogger(JcrItemResource.class);
+
     private final ResourceResolver resourceResolver;
 
     private final String path;
@@ -79,6 +89,27 @@ abstract class JcrItemResource extends A
         return result;
     }
 
+    protected void setContentLength(final Property property) throws RepositoryException {
+        if (property.isMultiple()) {
+            return;
+        }
+
+        try {
+            final long length;
+            if (property.getType() == PropertyType.BINARY ) {
+                // we're interested in the number of bytes, not the
+                // number of characters
+                length = property.getLength();
+            } else {
+                length = property.getString().getBytes("UTF-8").length;
+            }
+            getResourceMetadata().setContentLength(length);
+        } catch (UnsupportedEncodingException uee) {
+            LOGGER.warn("getPropertyContentLength: Cannot determine length of non-binary property {}: {}",
+                    toString(), uee);
+        }
+    }
+
     /**
      * Returns an iterator over the child resources or <code>null</code> if
      * there are none.

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java?rev=1053879&r1=1053878&r2=1053879&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResource.java Thu Dec 30 12:50:20 2010
@@ -176,9 +176,7 @@ class JcrNodeResource extends JcrItemRes
                 // if the node has a jcr:data property, use that property
                 if (content.hasProperty(JCR_DATA)) {
                     data = content.getProperty(JCR_DATA);
-
                 } else {
-
                     // otherwise try to follow default item trail
                     try {
                         Item item = content.getPrimaryItem();
@@ -187,16 +185,15 @@ class JcrNodeResource extends JcrItemRes
                         }
                         data = ((Property) item);
 
-                        // set the content lenght property as a side effect
+                        // set the content length property as a side effect
                         // for resources which are not nt:file based and whose
                         // data is not in jcr:content/jcr:data this will lazily
                         // set the correct content length
-                        getResourceMetadata().setContentLength(data.getLength());
+                        this.setContentLength(data);
 
                     } catch (ItemNotFoundException infe) {
                         // we don't actually care, but log for completeness
-                        LOGGER.debug("getInputStream: No primary items for "
-                            + toString(), infe);
+                        LOGGER.debug("getInputStream: No primary items for {}", toString(), infe);
                         data = null;
                     }
                 }

Modified: sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java?rev=1053879&r1=1053878&r2=1053879&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java (original)
+++ sling/trunk/bundles/jcr/resource/src/main/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResource.java Thu Dec 30 12:50:20 2010
@@ -18,9 +18,10 @@
  */
 package org.apache.sling.jcr.resource.internal.helper.jcr;
 
-import java.io.InputStream;
-import java.util.Calendar;
-import java.util.Iterator;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import javax.jcr.Item;
 import javax.jcr.Node;
@@ -29,11 +30,9 @@ import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Value;
 import javax.jcr.ValueFormatException;
-
-import org.apache.sling.api.resource.Resource;
-import org.apache.sling.api.resource.ResourceResolver;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Iterator;
 
 class JcrPropertyResource extends JcrItemResource {
 
@@ -51,10 +50,13 @@ class JcrPropertyResource extends JcrIte
         super(resourceResolver, path);
         this.property = property;
         this.resourceType = getResourceTypeForNode(property.getParent())
-            + "/" + property.getName();
-        if (!property.isMultiple()) {
-            this.getResourceMetadata().setContentLength(property.getLength());
+                + "/" + property.getName();
+        if (PropertyType.BINARY != this.property.getType()) {
+            this.getResourceMetadata().setContentType("text/plain");
+            this.getResourceMetadata().setCharacterEncoding("UTF-8");
         }
+
+        this.setContentLength(property);
     }
 
     public String getResourceType() {

Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java?rev=1053879&r1=1053878&r2=1053879&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrItemResourceTestBase.java Thu Dec 30 12:50:20 2010
@@ -82,7 +82,7 @@ public class JcrItemResourceTestBase ext
         } else {
             try {
                 for (byte b : expected) {
-                    assertEquals(b, actual.read());
+                    assertEquals(b, (byte)actual.read());
                 }
             } finally {
                 try {

Modified: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java?rev=1053879&r1=1053878&r2=1053879&view=diff
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java (original)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrNodeResourceTest.java Thu Dec 30 12:50:20 2010
@@ -220,6 +220,28 @@ public class JcrNodeResourceTest extends
         assertTrue(crossCheck2.isEmpty());
     }
 
+    public void testCorrectUTF8ByteLength() throws Exception {
+        byte[] utf8bytes = "Übersättigung".getBytes("UTF-8");
+        String name = "utf8file";
+        Node file = rootNode.addNode(name, JcrConstants.NT_FILE);
+        Node res = file.addNode(JcrConstants.JCR_CONTENT,
+            JcrConstants.NT_RESOURCE);
+
+        res.setProperty(JcrConstants.JCR_LASTMODIFIED, TEST_MODIFIED);
+        res.setProperty(JcrConstants.JCR_MIMETYPE, TEST_TYPE);
+        res.setProperty(JcrConstants.JCR_ENCODING, "UTF-8");
+        res.setProperty(JcrConstants.JCR_DATA, new ByteArrayInputStream(utf8bytes));
+
+        getSession().save();
+
+        file = rootNode.getNode(name);
+        JcrNodeResource jnr = new JcrNodeResource(null, file, null);
+
+        assertEquals(utf8bytes, jnr.adaptTo(InputStream.class));
+        assertEquals(utf8bytes.length, jnr.getResourceMetadata().getContentLength());
+    }
+
+
     private void setupResource(Node res) throws RepositoryException {
         res.setProperty(JcrConstants.JCR_LASTMODIFIED, TEST_MODIFIED);
         res.setProperty(JcrConstants.JCR_MIMETYPE, TEST_TYPE);

Added: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java?rev=1053879&view=auto
==============================================================================
--- sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java (added)
+++ sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java Thu Dec 30 12:50:20 2010
@@ -0,0 +1,77 @@
+/*
+ * 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.sling.jcr.resource.internal.helper.jcr;
+
+import static org.junit.Assert.assertEquals;
+
+import java.io.UnsupportedEncodingException;
+import java.util.HashMap;
+import java.util.Map.Entry;
+
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
+import javax.jcr.RepositoryException;
+
+import org.apache.sling.api.resource.ResourceResolver;
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.jmock.integration.junit4.JMock;
+import org.jmock.integration.junit4.JUnit4Mockery;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+/**
+ * JcrPropertyResourceTest ...
+ */
+@RunWith(JMock.class)
+public class JcrPropertyResourceTest {
+
+    protected final Mockery context = new JUnit4Mockery();
+
+    @Test
+    public void testCorrectUTF8ByteLength() throws RepositoryException, UnsupportedEncodingException {
+        final HashMap<Object, Integer> testData = new HashMap<Object, Integer>() {{
+            put("some random ascii string", PropertyType.STRING);
+            put("русский язык", PropertyType.STRING);
+            put("贛語", PropertyType.STRING);
+            put("string with ümlaut", PropertyType.STRING);
+            put(true, PropertyType.BOOLEAN);
+            put(1000L, PropertyType.LONG);
+        }};
+
+        final ResourceResolver resolver = this.context.mock(ResourceResolver.class);
+        for (final Entry<Object, Integer> data : testData.entrySet()) {
+            final String stringValue = data.getKey().toString();
+            final long stringByteLength =  stringValue.getBytes("UTF-8").length;
+            final Property property = this.context.mock(Property.class, stringValue);
+            this.context.checking(new Expectations() {{
+                ignoring(resolver);
+                allowing(property).getParent();
+                allowing(property).getName();
+                allowing(property).isMultiple(); will(returnValue(false));
+                allowing(property).getLength(); will(returnValue((long) stringValue.length()));
+
+                allowing(property).getType(); will(returnValue(data.getValue()));
+                allowing(property).getString(); will(returnValue(stringValue));
+            }});
+            final JcrPropertyResource propResource = new JcrPropertyResource(resolver, "/path/to/string-property", property);
+            assertEquals("Byte length of " +  stringValue, stringByteLength, propResource.getResourceMetadata().getContentLength());
+        }
+    }
+}

Propchange: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision rev url

Propchange: sling/trunk/bundles/jcr/resource/src/test/java/org/apache/sling/jcr/resource/internal/helper/jcr/JcrPropertyResourceTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain