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