You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:20:18 UTC

[sling-org-apache-sling-testing-resourceresolver-mock] 10/15: SLING-3889 Make compatible to JCR resource

This is an automated email from the ASF dual-hosted git repository.

rombert pushed a commit to annotated tag org.apache.sling.testing.resourceresolver-mock-0.3.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-resourceresolver-mock.git

commit 1ad5976725f17c0dcd66a042ec1149cf63cb53f7
Author: sseifert <ss...@unknown>
AuthorDate: Tue Sep 9 12:47:37 2014 +0000

    SLING-3889 Make compatible to JCR resource
    
    git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/testing/resourceresolver-mock@1623814 13f79535-47bb-0310-9956-ffa450edef68
---
 pom.xml                                            |  14 ++
 ...MockResource.java => MockPropertyResource.java} |  51 ++----
 .../testing/resourceresolver/MockResource.java     |  17 +-
 .../resourceresolver/MockResourceResolver.java     |  30 +++-
 .../testing/resourceresolver/MockValueMap.java     | 109 ++++++++++++
 .../SlingCrudResourceResolverTest.java             | 187 +++++++++++++++++++++
 6 files changed, 365 insertions(+), 43 deletions(-)

diff --git a/pom.xml b/pom.xml
index 681b67d..a38f9d1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -69,10 +69,24 @@
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.compendium</artifactId>
             <version>4.3.0</version>
+            <scope>compile</scope>
         </dependency>
         <dependency>
             <groupId>javax.servlet</groupId>
             <artifactId>servlet-api</artifactId>
         </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+            <scope>compile</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
     </dependencies>
+    
 </project>
diff --git a/src/main/java/org/apache/sling/testing/resourceresolver/MockResource.java b/src/main/java/org/apache/sling/testing/resourceresolver/MockPropertyResource.java
similarity index 60%
copy from src/main/java/org/apache/sling/testing/resourceresolver/MockResource.java
copy to src/main/java/org/apache/sling/testing/resourceresolver/MockPropertyResource.java
index 7b80e2f..a6884f1 100644
--- a/src/main/java/org/apache/sling/testing/resourceresolver/MockResource.java
+++ b/src/main/java/org/apache/sling/testing/resourceresolver/MockPropertyResource.java
@@ -18,31 +18,29 @@
  */
 package org.apache.sling.testing.resourceresolver;
 
-import java.util.Map;
-
 import org.apache.sling.api.resource.AbstractResource;
-import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.ResourceMetadata;
 import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
 import org.apache.sling.api.resource.ValueMap;
-import org.apache.sling.api.wrappers.ModifiableValueMapDecorator;
-import org.apache.sling.api.wrappers.ValueMapDecorator;
-
-public class MockResource extends AbstractResource {
 
+/**
+ * Resource that wraps a property value.
+ */
+class MockPropertyResource extends AbstractResource {
+    
     private final String path;
-
-    private final Map<String, Object> props;
-
-    private final ResourceMetadata rm = new ResourceMetadata();
-
+    private final ValueMap props;
+    private final String key;
     private final ResourceResolver resolver;
+    private final ResourceMetadata rm = new ResourceMetadata();
 
-    public MockResource(final String path,
-            final Map<String, Object> props,
+    public MockPropertyResource(final String path,
+            final ValueMap props,
             final ResourceResolver resolver) {
         this.path = path;
         this.props = props;
+        this.key = ResourceUtil.getName(path);
         this.resolver = resolver;
     }
 
@@ -53,12 +51,12 @@ public class MockResource extends AbstractResource {
 
     @Override
     public String getResourceType() {
-        return (String)this.props.get(ResourceResolver.PROPERTY_RESOURCE_TYPE);
+        return null;
     }
 
     @Override
     public String getResourceSuperType() {
-        return (String)this.props.get("sling:resourceSuperType");
+        return null;
     }
 
     @Override
@@ -71,26 +69,13 @@ public class MockResource extends AbstractResource {
         return this.resolver;
     }
 
-    @SuppressWarnings("unchecked")
     @Override
-    public <AdapterType> AdapterType adaptTo(final Class<AdapterType> type) {
-        if ( type == ValueMap.class ) {
-            return (AdapterType)new ValueMapDecorator(this.props);
-        } else if ( type == ModifiableValueMap.class ) {
-            ((MockResourceResolver)this.resolver).addChanged(this.path, this.props);
-            return (AdapterType)new ModifiableValueMapDecorator(this.props);
+    public <AdapterType> AdapterType adaptTo(Class<AdapterType> type) {
+        AdapterType value = props.get(key, type);
+        if (value!=null) {
+            return value;
         }
         return super.adaptTo(type);
     }
 
-    @Override
-    public ValueMap getValueMap() {
-        return new ValueMapDecorator(this.props);
-    }
-
-    @Override
-    public String toString() {
-        return "MockResource [path=" + path + ", props=" + props + "]";
-    }
-
 }
diff --git a/src/main/java/org/apache/sling/testing/resourceresolver/MockResource.java b/src/main/java/org/apache/sling/testing/resourceresolver/MockResource.java
index 7b80e2f..a8ed2f5 100644
--- a/src/main/java/org/apache/sling/testing/resourceresolver/MockResource.java
+++ b/src/main/java/org/apache/sling/testing/resourceresolver/MockResource.java
@@ -32,17 +32,19 @@ public class MockResource extends AbstractResource {
 
     private final String path;
 
-    private final Map<String, Object> props;
+    private final ValueMap props;
 
     private final ResourceMetadata rm = new ResourceMetadata();
 
     private final ResourceResolver resolver;
 
+    static final String JCR_PRIMARYTYPE = "jcr:primaryType";
+    
     public MockResource(final String path,
             final Map<String, Object> props,
             final ResourceResolver resolver) {
         this.path = path;
-        this.props = props;
+        this.props = (props instanceof MockValueMap) ? (MockValueMap)props : new MockValueMap(props);
         this.resolver = resolver;
     }
 
@@ -53,12 +55,17 @@ public class MockResource extends AbstractResource {
 
     @Override
     public String getResourceType() {
-        return (String)this.props.get(ResourceResolver.PROPERTY_RESOURCE_TYPE);
+        String resourceType = this.props.get(ResourceResolver.PROPERTY_RESOURCE_TYPE, String.class);
+        if (resourceType == null) {
+            // fallback to jcr:primaryType if not resouce type exists (to mimick JCR resource behavior)
+            resourceType = this.props.get(JCR_PRIMARYTYPE, String.class);
+        }
+        return resourceType;
     }
 
     @Override
     public String getResourceSuperType() {
-        return (String)this.props.get("sling:resourceSuperType");
+        return this.props.get("sling:resourceSuperType", String.class);
     }
 
     @Override
@@ -85,7 +92,7 @@ public class MockResource extends AbstractResource {
 
     @Override
     public ValueMap getValueMap() {
-        return new ValueMapDecorator(this.props);
+        return this.props;
     }
 
     @Override
diff --git a/src/main/java/org/apache/sling/testing/resourceresolver/MockResourceResolver.java b/src/main/java/org/apache/sling/testing/resourceresolver/MockResourceResolver.java
index 05e41c4..b5c4682 100644
--- a/src/main/java/org/apache/sling/testing/resourceresolver/MockResourceResolver.java
+++ b/src/main/java/org/apache/sling/testing/resourceresolver/MockResourceResolver.java
@@ -36,6 +36,8 @@ import org.apache.sling.api.resource.LoginException;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.api.resource.ValueMap;
 import org.osgi.service.event.Event;
 
 public class MockResourceResolver extends SlingAdaptable implements ResourceResolver {
@@ -86,6 +88,25 @@ public class MockResourceResolver extends SlingAdaptable implements ResourceReso
 
     @Override
     public Resource getResource(final String path) {
+        Resource resource = getResourceInternal(path);
+        
+        // if not resource found check if this is a reference to a property
+        if (resource == null) {
+            String name = ResourceUtil.getName(path);
+            String parentPath = ResourceUtil.getParent(path);
+            Resource parentResource = getResourceInternal(parentPath);
+            if (parentResource!=null) {
+                ValueMap props = parentResource.getValueMap();
+                if (props.containsKey(name)) {
+                    return new MockPropertyResource(path, props, this);
+                }
+            }
+        }
+        
+        return resource;
+    }
+    
+    private Resource getResourceInternal(final String path) {
         if ( path.startsWith("/") ) {
             if ( this.deletedResources.contains(path) ) {
                 return null;
@@ -186,7 +207,6 @@ public class MockResourceResolver extends SlingAdaptable implements ResourceReso
     @Override
     public ResourceResolver clone(Map<String, Object> authenticationInfo)
             throws LoginException {
-        // TODO Auto-generated method stub
         return null;
     }
 
@@ -202,7 +222,6 @@ public class MockResourceResolver extends SlingAdaptable implements ResourceReso
 
     @Override
     public String getUserID() {
-        // TODO Auto-generated method stub
         return null;
     }
 
@@ -254,9 +273,10 @@ public class MockResourceResolver extends SlingAdaptable implements ResourceReso
         if ( properties == null ) {
             properties = new HashMap<String, Object>();
         }
-        this.temporaryResources.put(path, properties);
-
-        return new MockResource(path, properties, this);
+        
+        Resource mockResource = new MockResource(path, properties, this);
+        this.temporaryResources.put(path, mockResource.getValueMap());
+        return mockResource;
     }
 
     @Override
diff --git a/src/main/java/org/apache/sling/testing/resourceresolver/MockValueMap.java b/src/main/java/org/apache/sling/testing/resourceresolver/MockValueMap.java
new file mode 100644
index 0000000..4fe009a
--- /dev/null
+++ b/src/main/java/org/apache/sling/testing/resourceresolver/MockValueMap.java
@@ -0,0 +1,109 @@
+/*
+ * 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.testing.resourceresolver;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.sling.api.wrappers.ValueMapDecorator;
+
+/**
+ * ValueMap for mocked resources to mimick JCR-like behavior.
+ * <p>Implements the following conversions:</p>
+ * <ul>
+ * <li>Converts all Date values to Calendar objects internally and vice versa.</li>
+ * <li>Converts InputStream to byte array and vice versa.</li>
+ * <ul>
+ */
+public class MockValueMap extends ValueMapDecorator {
+    
+    public MockValueMap() {
+        this(new HashMap<String, Object>());
+    }
+
+    public MockValueMap(Map<String,Object> map) {
+        super(convertForWrite(map));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public <T> T get(String name, Class<T> type) {
+        if (type==Date.class) {
+            Calendar calendar = super.get(name, Calendar.class);
+            if (calendar != null) {
+                return (T)calendar.getTime();
+            }
+            else {
+                return null;
+            }
+        }
+        else if (type==InputStream.class) {
+            byte[] data = super.get(name, byte[].class);
+            if (data!=null) {
+                return (T)new ByteArrayInputStream(data);
+            }
+            else {
+                return null;
+            }
+        }
+        return super.get(name, type);
+    }
+
+    @Override
+    public Object put(String key, Object value) {
+        return super.put(key, convertForWrite(value));
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void putAll(Map<? extends String, ?> map) {
+        super.putAll((Map<? extends String, ?>)convertForWrite(map));
+    }
+    
+    private static Object convertForWrite(Object value) {
+        if (value instanceof Date) {
+            Calendar calendar = Calendar.getInstance();
+            calendar.setTime((Date)value);
+            value = calendar;
+        }
+        else if (value instanceof InputStream) {
+            try {
+                value = IOUtils.toByteArray((InputStream)value);
+            } catch (IOException ex) {
+                throw new RuntimeException("Unable to convert input stream to byte array.");
+            }
+        }
+        return value;
+    }
+    
+    private static Map<String, Object> convertForWrite(Map<String, Object> map) {
+        Map<String,Object> newMap = new HashMap<String, Object>();
+        for (Map.Entry<String, Object> entry : map.entrySet()) {
+            newMap.put(entry.getKey(), convertForWrite(entry.getValue()));
+        }
+        return newMap;
+    }
+
+}
diff --git a/src/test/java/org/apache/sling/testing/resourceresolver/SlingCrudResourceResolverTest.java b/src/test/java/org/apache/sling/testing/resourceresolver/SlingCrudResourceResolverTest.java
new file mode 100644
index 0000000..617773f
--- /dev/null
+++ b/src/test/java/org/apache/sling/testing/resourceresolver/SlingCrudResourceResolverTest.java
@@ -0,0 +1,187 @@
+/*
+ * 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.testing.resourceresolver;
+
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.sling.api.resource.LoginException;
+import org.apache.sling.api.resource.PersistenceException;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceResolver;
+import org.apache.sling.api.resource.ValueMap;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * Implements simple write and read resource and values test
+ * Sling CRUD API is used to create the test data.
+ */
+public class SlingCrudResourceResolverTest {
+
+    private static final String STRING_VALUE = "value1";
+    private static final String[] STRING_ARRAY_VALUE = new String[] { "value1", "value2" };
+    private static final int INTEGER_VALUE = 25;
+    private static final double DOUBLE_VALUE = 3.555d;
+    private static final boolean BOOLEAN_VALUE = true;
+    private static final Date DATE_VALUE = new Date(10000);
+    private static final Calendar CALENDAR_VALUE = Calendar.getInstance();
+    private static final byte[] BINARY_VALUE = new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06 };
+
+    private static final String NT_UNSTRUCTURED = "nt:unstructured";
+
+    private ResourceResolver resourceResolver;
+    protected Resource testRoot;
+
+    @Before
+    public final void setUp() throws IOException, LoginException {
+        this.resourceResolver = new MockResourceResolverFactory().getResourceResolver(null);
+
+        // prepare some test data using Sling CRUD API
+        Resource rootNode = getTestRootResource();
+
+        Map<String, Object> props = new HashMap<String, Object>();
+        props.put(MockResource.JCR_PRIMARYTYPE, NT_UNSTRUCTURED);
+        props.put("stringProp", STRING_VALUE);
+        props.put("stringArrayProp", STRING_ARRAY_VALUE);
+        props.put("integerProp", INTEGER_VALUE);
+        props.put("doubleProp", DOUBLE_VALUE);
+        props.put("booleanProp", BOOLEAN_VALUE);
+        props.put("dateProp", DATE_VALUE);
+        props.put("calendarProp", CALENDAR_VALUE);
+        props.put("binaryProp", new ByteArrayInputStream(BINARY_VALUE));
+        Resource node1 = this.resourceResolver.create(rootNode, "node1", props);
+
+        this.resourceResolver.create(node1, "node11", ValueMap.EMPTY);
+        this.resourceResolver.create(node1, "node12", ValueMap.EMPTY);
+
+        this.resourceResolver.commit();
+    }
+
+    @After
+    public final void tearDown() {
+        this.testRoot = null;
+    }
+
+    /**
+     * Return a test root resource, created on demand, with a unique path
+     * @throws PersistenceException
+     */
+    private Resource getTestRootResource() throws PersistenceException {
+        if (this.testRoot == null) {
+            final Resource root = this.resourceResolver.getResource("/");
+            this.testRoot = this.resourceResolver.create(root, "test", ValueMap.EMPTY);
+        }
+        return this.testRoot;
+    }
+
+    @Test
+    public void testSimpleProperties() throws IOException {
+        Resource resource1 = this.resourceResolver.getResource(getTestRootResource().getPath() + "/node1");
+        assertNotNull(resource1);
+        assertEquals("node1", resource1.getName());
+
+        ValueMap props = resource1.getValueMap();
+        assertEquals(STRING_VALUE, props.get("stringProp", String.class));
+        assertArrayEquals(STRING_ARRAY_VALUE, props.get("stringArrayProp", String[].class));
+        assertEquals((Integer) INTEGER_VALUE, props.get("integerProp", Integer.class));
+        assertEquals(DOUBLE_VALUE, props.get("doubleProp", Double.class), 0.0001);
+        assertEquals(BOOLEAN_VALUE, props.get("booleanProp", Boolean.class));
+    }
+
+    @Test
+    public void testDateProperty() throws IOException {
+        Resource resource1 = this.resourceResolver.getResource(getTestRootResource().getPath() + "/node1");
+        ValueMap props = resource1.getValueMap();
+        assertEquals(DATE_VALUE, props.get("dateProp", Date.class));
+    }
+
+    @Test
+    public void testDatePropertyToCalendar() throws IOException {
+        Resource resource1 = this.resourceResolver.getResource(getTestRootResource().getPath() + "/node1");
+        ValueMap props = resource1.getValueMap();
+        Calendar calendarValue = props.get("dateProp", Calendar.class);
+        assertNotNull(calendarValue);
+        assertEquals(DATE_VALUE, calendarValue.getTime());
+    }
+    
+    @Test
+    public void testCalendarProperty() throws IOException {
+        Resource resource1 = this.resourceResolver.getResource(getTestRootResource().getPath() + "/node1");
+        ValueMap props = resource1.getValueMap();
+        assertEquals(CALENDAR_VALUE.getTime(), props.get("calendarProp", Calendar.class).getTime());
+    }
+
+    @Test
+    public void testCalendarPropertyToDate() throws IOException {
+        Resource resource1 = this.resourceResolver.getResource(getTestRootResource().getPath() + "/node1");
+        ValueMap props = resource1.getValueMap();
+        Date dateValue = props.get("calendarProp", Date.class);
+        assertNotNull(dateValue);
+        assertEquals(CALENDAR_VALUE.getTime(), dateValue);
+    }
+    
+    @Test
+    public void testListChildren() throws IOException {
+        Resource resource1 = this.resourceResolver.getResource(getTestRootResource().getPath() + "/node1");
+
+        Iterator<Resource> children = resource1.listChildren();
+        assertEquals("node11", children.next().getName());
+        assertEquals("node12", children.next().getName());
+        assertFalse(children.hasNext());
+    }
+
+    @Test
+    public void testBinaryData() throws IOException {
+        Resource resource1 = this.resourceResolver.getResource(getTestRootResource().getPath() + "/node1");
+
+        Resource binaryPropResource = resource1.getChild("binaryProp");
+        InputStream is = binaryPropResource.adaptTo(InputStream.class);
+        byte[] dataFromResource = IOUtils.toByteArray(is);
+        is.close();
+        assertArrayEquals(BINARY_VALUE, dataFromResource);
+
+        // read second time to ensure not the original input stream was returned
+        // and this time using another syntax
+        InputStream is2 = resource1.getValueMap().get("binaryProp", InputStream.class);
+        byte[] dataFromResource2 = IOUtils.toByteArray(is2);
+        is2.close();
+        assertArrayEquals(BINARY_VALUE, dataFromResource2);
+    }
+
+    @Test
+    public void testPrimaryTypeResourceType() throws PersistenceException {
+        Resource resource1 = this.resourceResolver.getResource(getTestRootResource().getPath() + "/node1");
+        assertEquals(NT_UNSTRUCTURED, resource1.getResourceType());
+    }
+
+}

-- 
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.