Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MODE-2182 Added 2 methods to the REST service which allow uploading binaries under a [nt:folder]/[nt:file] hierarchy, creating the hierarchy if it doesn't exist. #1093

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,6 @@
import java.util.Iterator;
import java.util.List;
import javax.ws.rs.core.MediaType;
import junit.framework.AssertionFailedError;
import org.apache.http.HttpEntity;
import org.apache.http.HttpHost;
import org.apache.http.HttpResponse;
Expand Down Expand Up @@ -62,7 +61,9 @@
import org.modeshape.common.text.UrlEncoder;
import org.modeshape.common.util.IoUtil;
import org.modeshape.common.util.StringUtil;
import org.modeshape.jcr.api.JcrConstants;
import org.modeshape.web.jcr.rest.handler.AbstractHandler;
import junit.framework.AssertionFailedError;

/**
* Test of the ModeShape JCR REST resource. Note that this test case uses a very low-level API to construct requests and
Expand Down Expand Up @@ -546,6 +547,10 @@ protected String queryUrl( String... additionalPathSegments ) {
return RestHelper.urlFrom(REPOSITORY_NAME + "/default/" + RestHelper.QUERY_METHOD_NAME, additionalPathSegments);
}

protected String uploadUrl(String...additionalPathSegments) {
return RestHelper.urlFrom(REPOSITORY_NAME + "/default/" + RestHelper.UPLOAD_METHOD_NAME, additionalPathSegments);
}

protected Response doGet() throws Exception {
return new Response(newDefaultRequest(HttpGet.class, null, null));
}
Expand Down Expand Up @@ -798,6 +803,7 @@ protected class Response {
private final HttpResponse response;
private byte[] content;
private String contentString;
private JSONObject contentJSON;

protected Response( HttpRequestBase request ) {
try {
Expand Down Expand Up @@ -920,7 +926,10 @@ protected String hasNodeIdentifier() throws Exception {
}

protected JSONObject json() throws Exception {
return new JSONObject(contentAsString());
if (contentJSON == null) {
contentJSON = new JSONObject(contentAsString());
}
return contentJSON;
}

protected JSONObject children() throws Exception {
Expand All @@ -934,6 +943,13 @@ protected String contentAsString() {
return contentString;
}

protected Response hasPrimaryType(String primaryType) throws Exception {
JSONObject json = json();
assertTrue("jcr:primary type property not found", json.has(JcrConstants.JCR_PRIMARY_TYPE));
assertEquals(primaryType, json().getString(JcrConstants.JCR_PRIMARY_TYPE));
return this;
}

protected byte[] contentAsBytes() {
return content;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

/**
* Unit test for the v2 version of the rest service: {@link ModeShapeRestService}
*
*
* @author Horia Chiorean
*/
public class ModeShapeRestServiceTest extends JcrResourcesTest {
Expand Down Expand Up @@ -285,7 +285,8 @@ public void shouldRetrieveBinaryPropertyValue() throws Exception {
.hasMimeType(MediaType.TEXT_PLAIN)
.hasContentDisposition(
RestBinaryHandler.DEFAULT_CONTENT_DISPOSITION_PREFIX
+ TEST_NODE);
+ TEST_NODE
);

assertEquals("testValue", response.contentAsString());
}
Expand Down Expand Up @@ -322,7 +323,8 @@ public void shouldReturnNotFoundForNonBinaryProperty() throws Exception {
public void shouldCreateBinaryProperty() throws Exception {
doPost((String)null, itemsUrl(TEST_NODE)).isCreated();
doPost(fileStream("v2/post/binary.pdf"), binaryUrl(TEST_NODE, binaryPropertyName())).isCreated()
.isJSONObjectLikeFile(newBinaryProperty());
.isJSONObjectLikeFile(
newBinaryProperty());
Response response = doGet(binaryUrl(TEST_NODE, binaryPropertyName())).isOk();

byte[] expectedBinaryContent = IoUtil.readBytes(fileStream("v2/post/binary.pdf"));
Expand Down Expand Up @@ -455,15 +457,15 @@ public void shouldGetNodeByIdentifier() throws Exception {
}

@Test
@FixFor( "MODE-1816" )
@FixFor("MODE-1816")
public void shouldAllowPostingNodeWithMixinAndPrimaryTypesPropertiesAfterProperties() throws Exception {
doPost(nodeWithMixinAfterPropsRequest(), itemsUrl(TEST_NODE)).isCreated()
.isJSONObjectLikeFile(nodeWithMixinAfterPropsResponse());
doGet(itemsUrl(TEST_NODE)).isOk().isJSONObjectLikeFile(nodeWithMixinAfterPropsResponse());
}

@Test
@FixFor( "MODE-1901" )
@FixFor("MODE-1901")
public void shouldComputePlainTextPlanForJcrSql2Query() throws Exception {
// No need to create any data, since we are not executing the query ...
String query = "SELECT * FROM [nt:unstructured] WHERE ISCHILDNODE('/" + TEST_NODE + "')";
Expand All @@ -475,7 +477,7 @@ public void shouldComputePlainTextPlanForJcrSql2Query() throws Exception {
}

@Test
@FixFor( "MODE-1901" )
@FixFor("MODE-1901")
public void shouldComputeJsonPlanForJcrSql2Query() throws Exception {
// No need to create any data, since we are not executing the query ...
String query = "SELECT * FROM [nt:unstructured] WHERE ISCHILDNODE('/" + TEST_NODE + "')";
Expand All @@ -491,7 +493,7 @@ protected String queryPlanUrl( String... additionalPathSegments ) {
}

@Test
@FixFor( "MODE-2048")
@FixFor( "MODE-2048" )
public void shouldAllowChildrenUpdateViaID() throws Exception {
/**
* testNode
Expand Down Expand Up @@ -530,7 +532,7 @@ public void shouldAllowChildrenUpdateViaID() throws Exception {
}

@Test
@FixFor( "MODE-2048")
@FixFor("MODE-2048")
public void shouldPerformChildReordering() throws Exception {
/**
* testNode
Expand All @@ -549,7 +551,7 @@ public void shouldPerformChildReordering() throws Exception {
JSONObject children = doPut("v2/put/node_multiple_children_reorder1.json", itemsUrl(TEST_NODE)).isOk().children();

List<String> actualOrder = new ArrayList<String>();
for (Iterator<?> iterator = children.keys(); iterator.hasNext();) {
for (Iterator<?> iterator = children.keys(); iterator.hasNext(); ) {
actualOrder.add(iterator.next().toString());
}
assertEquals("Invalid child order", Arrays.asList("child3", "child2", "child1"), actualOrder);
Expand All @@ -562,14 +564,14 @@ public void shouldPerformChildReordering() throws Exception {
*/
children = doPut("v2/put/node_multiple_children_reorder2.json", itemsUrl(TEST_NODE)).isOk().children();
actualOrder = new ArrayList<String>();
for (Iterator<?> iterator = children.keys(); iterator.hasNext();) {
for (Iterator<?> iterator = children.keys(); iterator.hasNext(); ) {
actualOrder.add(iterator.next().toString());
}
assertEquals("Invalid child order", Arrays.asList("child2", "child3", "child1"), actualOrder);
}

@Test
@FixFor( "MODE-2048")
@FixFor("MODE-2048")
public void shouldMoveNode() throws Exception {
/**
* node1
Expand All @@ -578,7 +580,8 @@ public void shouldMoveNode() throws Exception {
* - child3
*/
try {
JSONObject children = doPost("v2/post/node_multiple_children_request.json", itemsUrl("node1")).isCreated().children();
JSONObject children = doPost("v2/post/node_multiple_children_request.json", itemsUrl("node1")).isCreated()
.children();
String child2Id = children.getJSONObject("child2").getString(ID_KEY);

/**
Expand All @@ -603,7 +606,7 @@ public void shouldMoveNode() throws Exception {
}

@Test
@FixFor( "MODE-2056" )
@FixFor("MODE-2056")
public void shouldCloseActiveSessions() throws Exception {
//execute 3 requests
doPost("v2/post/node_multiple_children_request.json", itemsUrl(TEST_NODE)).isCreated();
Expand All @@ -618,7 +621,7 @@ public void shouldCloseActiveSessions() throws Exception {
}

@Test
@FixFor( "MODE-2170" )
@FixFor("MODE-2170")
public void shouldAllowUpdatingMultivaluedProperty() throws Exception {
doPost("v2/post/node_multivalue_prop_request.json", itemsUrl(TEST_NODE)).isCreated();
doPut("v2/put/node_multivalue_prop_request.json", itemsUrl(TEST_NODE))
Expand All @@ -628,7 +631,7 @@ public void shouldAllowUpdatingMultivaluedProperty() throws Exception {
}

@Test
@FixFor( "MODE-2181" )
@FixFor("MODE-2181")
public void shouldAllowCreatingSNS() throws Exception {
doPost("v2/post/node_with_sns_request.json", itemsUrl(TEST_NODE)).isCreated();
doGet(itemsUrl(TEST_NODE, "foo[1]")).isOk();
Expand All @@ -638,7 +641,7 @@ public void shouldAllowCreatingSNS() throws Exception {
}

@Test
@FixFor( "MODE-2181" )
@FixFor("MODE-2181")
public void shouldAllowUpdatingSNSViaArray() throws Exception {
doPost("v2/post/node_with_sns_request.json", itemsUrl(TEST_NODE)).isCreated();
doPut("v2/put/node_with_sns_edit_request.json", itemsUrl(TEST_NODE)).isOk();
Expand All @@ -651,7 +654,7 @@ public void shouldAllowUpdatingSNSViaArray() throws Exception {
}

@Test
@FixFor( "MODE-2181" )
@FixFor("MODE-2181")
public void shouldAllowUpdatingSNSViaObject() throws Exception {
doPost("v2/post/node_with_sns_request.json", itemsUrl(TEST_NODE)).isCreated();
doPut("v2/put/node_with_sns_edit_alt_request.json", itemsUrl(TEST_NODE)).isOk();
Expand All @@ -664,11 +667,98 @@ public void shouldAllowUpdatingSNSViaObject() throws Exception {
}

@Test
@FixFor( "MODE-2181" )
@FixFor("MODE-2181")
public void shouldAllowDeletingSNS() throws Exception {
doPost("v2/post/node_with_sns_request.json", itemsUrl(TEST_NODE)).isCreated();
doDelete("v2/delete/sns_nodes_delete.json", itemsUrl()).isOk();
doGet(itemsUrl(TEST_NODE, "foo[1]")).isNotFound();
doGet(itemsUrl(TEST_NODE, "foo[2]")).isNotFound();
}

@Test
@FixFor("MODE-2182")
public void shouldUploadFileUnderRootUsingStream() throws Exception {
try {
assertUpload("testFile1", true, false);
} catch (Exception e) {
doDelete(itemsUrl("testFile1")).isDeleted();
}
}

@Test
@FixFor( "MODE-2182" )
public void shouldUploadFileUnderRootUsingForm() throws Exception {
try {
assertUpload("testFile2", true, true);
} finally {
doDelete(itemsUrl("testFile2")).isDeleted();
}
}

@Test
@FixFor( "MODE-2182" )
public void shouldUploadFileAndCreateHierarchy() throws Exception {
try {
assertUpload("node1/node2/file", true, false);
doGet(itemsUrl("node1")).isOk().hasPrimaryType("nt:folder");
doGet(itemsUrl("node1/node2")).isOk().hasPrimaryType("nt:folder");
doGet(itemsUrl("node1/node2/file")).isOk().hasPrimaryType("nt:file");
} finally {
doDelete(itemsUrl("node1"));
}
}

@Test
@FixFor( "MODE-2182" )
public void shouldUploadFileAndCreatePartialHierarchy() throws Exception {
try {
doPost("v2/post/folder.json", itemsUrl("node1")).isCreated().hasPrimaryType("nt:folder");
doPost("v2/post/folder.json", itemsUrl("node1/node2")).isCreated().hasPrimaryType("nt:folder");
assertUpload("node1/node2/file", true, false);
doGet(itemsUrl("node1/node2/file")).isOk().hasPrimaryType("nt:file");
} finally {
doDelete(itemsUrl("node1"));
}
}

@Test
@FixFor( "MODE-2182" )
public void shouldModifyExistingFileViaUpload() throws Exception {
try {
doPost("v2/post/folder.json", itemsUrl("node1")).isCreated().hasPrimaryType("nt:folder");
doPost("v2/post/folder.json", itemsUrl("node1/node2")).isCreated().hasPrimaryType("nt:folder");
doPost("v2/post/file.json", itemsUrl("node1/node2/file")).isCreated().hasPrimaryType("nt:file");
assertUpload("node1/node2/file", false, false);
} finally {
doDelete(itemsUrl("node1"));
}
}

@Test
@FixFor( "MODE-2182" )
public void shouldNotAllowUploadIfTypeInvalid() throws Exception {
try {
doPost("v2/post/folder.json", itemsUrl("node1")).isCreated().hasPrimaryType("nt:folder");
doPost(fileStream("v2/post/binary.pdf"), uploadUrl("node1")).isBadRequest();
} finally {
doDelete(itemsUrl("node1"));
}
}

private void assertUpload( String url, boolean expectCreated, boolean useMultiPart ) throws Exception {
Response response = useMultiPart ?
doPostMultiPart("v2/post/binary.pdf", FileUploadForm.PARAM_NAME, uploadUrl(url),
MediaType.APPLICATION_OCTET_STREAM) :
doPost(fileStream("v2/post/binary.pdf"), uploadUrl(url));
if (expectCreated) {
response.isCreated();
} else {
response.isOk();
}
String binaryPropertyRequest = response.json().getString("jcr:data");
binaryPropertyRequest = binaryPropertyRequest.substring(binaryPropertyRequest.indexOf(
getServerContext()) + getServerContext().length());
byte[] uploaded = doGet(binaryPropertyRequest).isOk().contentAsBytes();
assertArrayEquals(IoUtil.readBytes(fileStream("v2/post/binary.pdf")), uploaded);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"jcr:primaryType":"nt:file",
"children":{
"jcr:content":{
"jcr:primaryType":"nt:resource",
"jcr:data" : "a string"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"jcr:primaryType":"nt:folder"
}