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 09:58:13 UTC
[sling-org-apache-sling-resourcebuilder] 04/36: SLING-5356 - add
file support
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.resourcebuilder-1.0.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-resourcebuilder.git
commit 9669c4c5578b8a5df64715900650ab03d1d5343c
Author: Bertrand Delacretaz <bd...@apache.org>
AuthorDate: Thu Dec 10 15:36:52 2015 +0000
SLING-5356 - add file support
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/bundles/commons/resourcebuilder@1719100 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 6 ++
.../sling/resourcebuilder/api/ResourceBuilder.java | 19 +++++
.../resourcebuilder/impl/ResourceBuilderImpl.java | 80 ++++++++++++++++++++--
.../impl/ResourceBuilderImplTest.java | 68 +++++++++++++++++-
src/test/resources/models.js | 1 +
src/test/resources/myapp.json | 4 ++
src/test/resources/text.html | 3 +
7 files changed, 174 insertions(+), 7 deletions(-)
diff --git a/pom.xml b/pom.xml
index b51e328..ca8feba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -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>
diff --git a/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java b/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java
index 7d43ec3..cd54db4 100644
--- a/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java
+++ b/src/main/java/org/apache/sling/resourcebuilder/api/ResourceBuilder.java
@@ -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();
diff --git a/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java b/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java
index 4e8899a..bb278d1 100644
--- a/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java
+++ b/src/main/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImpl.java
@@ -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 implements ResourceBuilder {
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 implements ResourceBuilder {
@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 implements ResourceBuilder {
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 implements ResourceBuilder {
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) {
diff --git a/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java b/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java
index 08e2364..dbf0253 100644
--- a/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java
+++ b/src/test/java/org/apache/sling/resourcebuilder/impl/ResourceBuilderImplTest.java
@@ -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);
+ }
}
diff --git a/src/test/resources/models.js b/src/test/resources/models.js
new file mode 100644
index 0000000..142f8d3
--- /dev/null
+++ b/src/test/resources/models.js
@@ -0,0 +1 @@
+function someJavascriptFunction() { return "yes, it worked." }
\ No newline at end of file
diff --git a/src/test/resources/myapp.json b/src/test/resources/myapp.json
new file mode 100644
index 0000000..bd3edd2
--- /dev/null
+++ b/src/test/resources/myapp.json
@@ -0,0 +1,4 @@
+{
+ "jcr:primaryType":"some:NodeType",
+ "sling:resourceType":"its/resource/type"
+}
\ No newline at end of file
diff --git a/src/test/resources/text.html b/src/test/resources/text.html
new file mode 100644
index 0000000..57dfc39
--- /dev/null
+++ b/src/test/resources/text.html
@@ -0,0 +1,3 @@
+<html>
+This is an html file
+</html>
\ No newline at end of file
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.