You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2015/12/10 16:36:52 UTC

svn commit: r1719100 - in /sling/trunk/bundles/commons/resourcebuilder: ./ src/main/java/org/apache/sling/resourcebuilder/api/ src/main/java/org/apache/sling/resourcebuilder/impl/ src/test/java/org/apache/sling/resourcebuilder/impl/ src/test/resources/

Author: bdelacretaz
Date: Thu Dec 10 15:36:52 2015
New Revision: 1719100

URL: http://svn.apache.org/viewvc?rev=1719100&view=rev
Log:
SLING-5356 - add file support

Added:
    sling/trunk/bundles/commons/resourcebuilder/src/test/resources/
    sling/trunk/bundles/commons/resourcebuilder/src/test/resources/models.js
    sling/trunk/bundles/commons/resourcebuilder/src/test/resources/myapp.json
    sling/trunk/bundles/commons/resourcebuilder/src/test/resources/text.html
Modified:
    sling/trunk/bundles/commons/resourcebuilder/pom.xml
    sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java
    sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java
    sling/trunk/bundles/commons/resourcebuilder/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java

Modified: sling/trunk/bundles/commons/resourcebuilder/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/resourcebuilder/pom.xml?rev=1719100&r1=1719099&r2=1719100&view=diff
==============================================================================
--- sling/trunk/bundles/commons/resourcebuilder/pom.xml (original)
+++ sling/trunk/bundles/commons/resourcebuilder/pom.xml Thu Dec 10 15:36:52 2015
@@ -75,6 +75,12 @@
             <scope>provided</scope>
         </dependency>
         <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>2.4</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
             <groupId>org.apache.sling</groupId>
             <artifactId>org.apache.sling.testing.sling-mock</artifactId>
             <version>1.6.0</version>

Modified: sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java?rev=1719100&r1=1719099&r2=1719100&view=diff
==============================================================================
--- sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java (original)
+++ sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java Thu Dec 10 15:36:52 2015
@@ -18,6 +18,8 @@
  */
 package org.apache.sling.resourcebuilder.api;
 
+import java.io.InputStream;
+
 import org.apache.sling.api.resource.Resource;
 
 /** Builds Sling Resources using a simple fluent API */
@@ -33,6 +35,23 @@ public interface ResourceBuilder {
      * @return this builder
      */
     ResourceBuilder resource(String relativePath, Object ... properties);
+
+    /** Create a file under the current parent resource
+     * @param filename The name of the created file
+     * @param data The file data
+     * @param mimeType If null, use the Sling MimeTypeService to set the mime type
+     * @param lastModified if < 0, current time is used
+     * @return this builder
+     */
+    ResourceBuilder file(String filename, InputStream data, String mimeType, long lastModified);
+    
+    /** Create a file under the current parent resource. Mime type is set using the 
+     *  Sling MimeTypeService, and last modified is set to current time.
+     * @param filename The name of the created file
+     * @param data The file data
+     * @return this builder
+     */
+    ResourceBuilder file(String filename, InputStream data);
     
     /** Commit created resources */
     ResourceBuilder commit();

Modified: sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java?rev=1719100&r1=1719099&r2=1719100&view=diff
==============================================================================
--- sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java (original)
+++ sling/trunk/bundles/commons/resourcebuilder/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java Thu Dec 10 15:36:52 2015
@@ -18,6 +18,11 @@
  */
 package org.apache.sling.resourcebuilder.impl;
 
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.sling.api.resource.ModifiableValueMap;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
@@ -33,6 +38,11 @@ public class ResourceBuilderImpl impleme
     private boolean hierarchyMode;
     
     public static final String JCR_PRIMARYTYPE = "jcr:primaryType";
+    public static final String JCR_MIMETYPE = "jcr:mimeType";
+    public static final String JCR_LASTMODIFIED = "jcr:lastModified";
+    public static final String JCR_DATA = "jcr:data";
+    public static final String JCR_CONTENT = "jcr:content";
+    public static final String NT_RESOURCE = "nt:resource";
     
     public ResourceBuilderImpl(Resource parent) {
         if(parent == null) {
@@ -58,7 +68,7 @@ public class ResourceBuilderImpl impleme
 
     @Override
     public ResourceBuilder resource(String relativePath, Object... properties) {
-        Resource created = null;
+        Resource r = null;
         if(relativePath.startsWith("/")) {
             throw new IllegalArgumentException("Path is not relative:" + relativePath);
         }
@@ -68,19 +78,32 @@ public class ResourceBuilderImpl impleme
         final Resource myParent = ensureResourceExists(parentPath);
         
         try {
-            created = currentParent.getResourceResolver().create(myParent, 
-                    ResourceUtil.getName(relativePath), MapArgsConverter.toMap(properties));
+            r = currentParent.getResourceResolver().getResource(fullPath);
+            final Map<String, Object> props = MapArgsConverter.toMap(properties);
+            if(r == null) {
+                r = currentParent.getResourceResolver().create(myParent, 
+                        ResourceUtil.getName(relativePath), props);
+            } else {
+                // Resource exists, set our properties
+                final ModifiableValueMap mvm = r.adaptTo(ModifiableValueMap.class);
+                if(mvm == null) {
+                    throw new IllegalStateException("Cannot modify properties of " + r.getPath());
+                }
+                for(Map.Entry <String, Object> e : props.entrySet()) {
+                    mvm.put(e.getKey(), e.getValue());
+                }
+            }
         } catch(PersistenceException pex) {
             throw new RuntimeException(
                     "PersistenceException while creating Resource " + relativePath 
                     + " under " + currentParent.getPath(), pex);
         }
         
-        if(created == null) {
-            throw new RuntimeException("Failed to created resource " + relativePath 
+        if(r == null) {
+            throw new RuntimeException("Failed to get or create resource " + relativePath 
                     + " under " + currentParent.getPath());
         } else if(hierarchyMode) {
-            currentParent = created;
+            currentParent = r;
         }
         return this;
     }
@@ -112,6 +135,51 @@ public class ResourceBuilderImpl impleme
             throw new RuntimeException("Unable to create intermediate resource at " + path, ex);
         }
     }
+    
+    @Override
+    public ResourceBuilder file(String filename, InputStream data, String mimeType, long lastModified) {
+        Resource file = null;
+        final ResourceResolver resolver = currentParent.getResourceResolver();
+        final String name = ResourceUtil.getName(filename);
+        
+        if(!filename.equals(name)) {
+            throw new IllegalArgumentException("Filename must not be a path:" + filename + " -> " + name);
+        }
+        if(data == null) {
+            throw new IllegalArgumentException("Data is null for file " + filename);
+        }
+        
+        try {
+            final String fullPath = currentParent.getPath() + "/" + name;
+            if(resolver.getResource(fullPath) != null) {
+                throw new IllegalStateException("Resource already exists:" + fullPath);
+            }
+            file = resolver.create(currentParent, name, null);
+            final Map<String, Object> props = new HashMap<String, Object>();
+            props.put(JCR_PRIMARYTYPE, NT_RESOURCE);
+            // TODO get mime type from MimeTypeService
+            props.put(JCR_MIMETYPE, mimeType);
+            props.put(JCR_LASTMODIFIED, lastModified >= 0 ? lastModified : System.currentTimeMillis());
+            props.put(JCR_DATA, data);
+            resolver.create(file, JCR_CONTENT, props); 
+        } catch(PersistenceException pex) {
+            throw new RuntimeException("Unable to create file under " + currentParent.getPath(), pex);
+        }
+        
+        if(file == null) {
+            throw new RuntimeException("Unable to get or created file resource " + filename + " under " + currentParent.getPath());
+        }
+        if(hierarchyMode) {
+            currentParent = file;
+        }
+        
+        return this;
+    }
+
+    @Override
+    public ResourceBuilder file(String filename, InputStream data) {
+        return file(filename, data, null, -1);
+    }
 
     @Override
     public ResourceBuilder withIntermediatePrimaryType(String primaryType) {

Modified: sling/trunk/bundles/commons/resourcebuilder/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/resourcebuilder/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java?rev=1719100&r1=1719099&r2=1719100&view=diff
==============================================================================
--- sling/trunk/bundles/commons/resourcebuilder/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java (original)
+++ sling/trunk/bundles/commons/resourcebuilder/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java Thu Dec 10 15:36:52 2015
@@ -18,12 +18,17 @@
  */
 package org.apache.sling.resourcebuilder.impl;
 
+import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
 import java.util.Map;
 import java.util.UUID;
 
+import org.apache.commons.io.IOUtils;
 import org.apache.sling.api.resource.PersistenceException;
 import org.apache.sling.api.resource.Resource;
 import org.apache.sling.api.resource.ResourceResolver;
@@ -61,6 +66,34 @@ public class ResourceBuilderImplTest {
         return result;
     }
     
+    /** Assert that a file exists and verify its properties. */
+    private void assertFile(String path, String mimeType, String expectedContent, Long lastModified) throws IOException {
+        final Resource r = assertResource(fullPath(path));
+        assertNotNull("Expecting resource to exist:" + path, r);
+        
+        // Files are stored according to the standard JCR structure
+        final Resource jcrContent = r.getChild(ResourceBuilderImpl.JCR_CONTENT);
+        assertNotNull("Expecting subresource:" + ResourceBuilderImpl.JCR_CONTENT, jcrContent);
+        final ValueMap vm = jcrContent.adaptTo(ValueMap.class);
+        assertNotNull("Expecting ValueMap for " + jcrContent.getPath(), vm);
+        assertEquals("Expecting nt:Resource type for " + jcrContent.getPath(), 
+                ResourceBuilderImpl.NT_RESOURCE, vm.get(ResourceBuilderImpl.JCR_PRIMARYTYPE));
+        assertEquals("Expecting the correct mime-type", mimeType, vm.get(ResourceBuilderImpl.JCR_MIMETYPE));
+        assertEquals("Expecting the correct last modified", lastModified, vm.get(ResourceBuilderImpl.JCR_LASTMODIFIED));
+        
+        final ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        final InputStream is = vm.get(ResourceBuilderImpl.JCR_DATA, InputStream.class);
+        assertNotNull("Expecting InputStream property on nt:resource:" + ResourceBuilderImpl.JCR_DATA, is);
+        IOUtils.copy(is, bos);
+        try {
+            final String content = new String(bos.toByteArray());
+            assertTrue("Expecting content to contain " + expectedContent, content.contains(expectedContent));
+        } finally {
+            bos.close();
+            is.close();
+        }
+    }
+    
     private String fullPath(String path) {
         return path.startsWith("/") ? path : testRootPath + "/" + path;
     }
@@ -176,7 +209,7 @@ public class ResourceBuilderImplTest {
     }
     
     @Test
-    public void buildATree() throws PersistenceException {
+    public void simpleTree() throws PersistenceException {
         getBuilder(testRootPath)
             .resource("a/b/c", "title", "foo", "count", 21)
             .siblingsMode()
@@ -196,4 +229,37 @@ public class ResourceBuilderImplTest {
         assertResource("a/b/c/2");
         assertResource("a/b/c/3");
     }
+    
+    @Test
+    public void treeWithFiles() throws PersistenceException, IOException {
+        getBuilder(testRootPath)
+            .resource("apps/myapp/components/resource")
+            .siblingsMode()
+            .file("models.js", getClass().getResourceAsStream("/models.js"), "MT1", 42)
+            .file("text.html", getClass().getResourceAsStream("/text.html"), "MT2", 43)
+            .resetParent()
+            .hierarchyMode()
+            .resource("apps")
+            .file("myapp.json", getClass().getResourceAsStream("/myapp.json"), "MT3", 44)
+            .resetParent()
+            .resource("apps/content/myapp/resource")
+            .resetParent()
+            .resource("apps/content", "title", "foo")
+            .file("myapp.json", getClass().getResourceAsStream("/myapp.json"), "MT4", 45)
+            .commit()
+            ;
+        
+        assertResource("apps/content/myapp/resource");
+        assertResource("apps/myapp/components/resource");
+        assertProperties("apps/content", "title", "foo");
+        
+        assertFile("apps/myapp/components/resource/models.js", 
+                "MT1", "function someJavascriptFunction()", 42L);
+        assertFile("apps/myapp/components/resource/text.html", 
+                "MT2", "This is an html file", 43L);
+        assertFile("apps/myapp.json", 
+                "MT3", "\"sling:resourceType\":\"its/resource/type\"", 44L);
+        assertFile("apps/content/myapp.json", 
+                "MT4", "\"sling:resourceType\":\"its/resource/type\"", 45L);
+    }
 }

Added: sling/trunk/bundles/commons/resourcebuilder/src/test/resources/models.js
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/resourcebuilder/src/test/resources/models.js?rev=1719100&view=auto
==============================================================================
--- sling/trunk/bundles/commons/resourcebuilder/src/test/resources/models.js (added)
+++ sling/trunk/bundles/commons/resourcebuilder/src/test/resources/models.js Thu Dec 10 15:36:52 2015
@@ -0,0 +1 @@
+function someJavascriptFunction() { return "yes, it worked." }
\ No newline at end of file

Added: sling/trunk/bundles/commons/resourcebuilder/src/test/resources/myapp.json
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/resourcebuilder/src/test/resources/myapp.json?rev=1719100&view=auto
==============================================================================
--- sling/trunk/bundles/commons/resourcebuilder/src/test/resources/myapp.json (added)
+++ sling/trunk/bundles/commons/resourcebuilder/src/test/resources/myapp.json Thu Dec 10 15:36:52 2015
@@ -0,0 +1,4 @@
+{
+    "jcr:primaryType":"some:NodeType",
+    "sling:resourceType":"its/resource/type"
+}
\ No newline at end of file

Added: sling/trunk/bundles/commons/resourcebuilder/src/test/resources/text.html
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/commons/resourcebuilder/src/test/resources/text.html?rev=1719100&view=auto
==============================================================================
--- sling/trunk/bundles/commons/resourcebuilder/src/test/resources/text.html (added)
+++ sling/trunk/bundles/commons/resourcebuilder/src/test/resources/text.html Thu Dec 10 15:36:52 2015
@@ -0,0 +1,3 @@
+<html>
+This is an html file
+</html>
\ No newline at end of file