/*
* (C) Copyright 2013 Nuxeo SA (http://nuxeo.com/) and others.
*
* Licensed 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.
*
* Contributors:
* dmetzler
*/
package org.nuxeo.ecm.restapi.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.ByteArrayInputStream;
import java.io.Serializable;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.inject.Inject;
import javax.ws.rs.core.Response.Status;
import org.apache.commons.io.IOUtils;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.nuxeo.ecm.core.api.Blob;
import org.nuxeo.ecm.core.api.Blobs;
import org.nuxeo.ecm.core.api.CoreSession;
import org.nuxeo.ecm.core.api.DocumentModel;
import org.nuxeo.ecm.core.api.PathRef;
import org.nuxeo.ecm.core.api.blobholder.BlobHolder;
import org.nuxeo.ecm.core.test.annotations.Granularity;
import org.nuxeo.ecm.core.test.annotations.RepositoryConfig;
import org.nuxeo.runtime.test.runner.Features;
import org.nuxeo.runtime.test.runner.FeaturesRunner;
import org.nuxeo.runtime.test.runner.Jetty;
import org.nuxeo.runtime.test.runner.LocalDeploy;
import org.nuxeo.runtime.transaction.TransactionHelper;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.multipart.BodyPart;
import com.sun.jersey.multipart.FormDataMultiPart;
import com.sun.jersey.multipart.file.StreamDataBodyPart;
/**
* @since 5.8
*/
@RunWith(FeaturesRunner.class)
@Features({ RestServerFeature.class })
@Jetty(port = 18090)
@RepositoryConfig(cleanup = Granularity.METHOD, init = RestServerInit.class)
@LocalDeploy("org.nuxeo.ecm.platform.restapi.test:multiblob-doctype.xml")
public class MultiBlobAccessTest extends BaseTest {
@Inject
CoreSession session;
private DocumentModel doc;
@Override
@Before
public void doBefore() throws Exception {
super.doBefore();
doc = session.createDocumentModel("/", "testBlob", "MultiBlobDoc");
addBlob(doc, Blobs.createBlob("one"));
addBlob(doc, Blobs.createBlob("two"));
doc = session.createDocument(doc);
TransactionHelper.commitOrRollbackTransaction();
TransactionHelper.startTransaction();
}
@Test
public void itDoesNotUpdateBlobsThroughDocEndpoint() throws Exception {
Map<String, String> headers = new HashMap<>();
headers.put("properties", "multiblob");
ClientResponse response = getResponse(RequestType.GET, "path" + doc.getPathAsString(), headers);
String docJsonIN = IOUtils.toString(response.getEntityInputStream());
response = getResponse(RequestType.PUT, "path" + doc.getPathAsString(), docJsonIN, headers);
DocumentModel doc = session.getDocument(new PathRef("/testBlob"));
assertEquals(2, ((List<?>) doc.getProperty("mb:blobs").getValue()).size());
Blob blob1 = (Blob) doc.getProperty("mb:blobs/0/content").getValue();
assertNotNull(blob1);
assertEquals("one", blob1.getString());
Blob blob2 = (Blob) doc.getProperty("mb:blobs/1/content").getValue();
assertNotNull(blob2);
assertEquals("two", blob2.getString());
}
@Test
public void itCanAccessBlobs() throws Exception {
// When i call the rest api
ClientResponse response = getResponse(RequestType.GET, "path" + doc.getPathAsString()
+ "/@blob/mb:blobs/0/content");
// Then i receive the content of the blob
assertEquals(Status.OK.getStatusCode(), response.getStatus());
assertEquals("one", response.getEntity(String.class));
response = getResponse(RequestType.GET, "path" + doc.getPathAsString() + "/@blob/mb:blobs/1/content");
assertEquals(Status.OK.getStatusCode(), response.getStatus());
assertEquals("two", response.getEntity(String.class));
}
@Test
public void itCanModifyABlob() throws Exception {
// Given a doc with a blob
// When i send a PUT with a new value on the blob
FormDataMultiPart form = new FormDataMultiPart();
BodyPart fdp = new StreamDataBodyPart("content", new ByteArrayInputStream("modifiedData".getBytes()));
form.bodyPart(fdp);
getResponse(RequestType.PUT, "path" + doc.getPathAsString() + "/@blob/mb:blobs/0/content", form);
form.close();
// The the blob is updated
fetchInvalidations();
doc = getTestBlob();
Blob blob = (Blob) doc.getPropertyValue("mb:blobs/0/content");
assertEquals("modifiedData", blob.getString());
}
@Test
public void itCanRemoveABlob() throws Exception {
// Given a doc with a blob
// When i send A DELETE command on its blob
getResponse(RequestType.DELETE, "path" + doc.getPathAsString() + "/@blob/mb:blobs/0/content");
// The the blob is reset
fetchInvalidations();
doc = getTestBlob();
Blob blob = (Blob) doc.getPropertyValue("mb:blobs/0/content");
assertNull(blob);
}
private DocumentModel getTestBlob() {
return session.getDocument(new PathRef("/testBlob"));
}
private void addBlob(DocumentModel doc, Blob blob) {
Map<String, Serializable> blobProp = new HashMap<>();
blobProp.put("content", (Serializable) blob);
@SuppressWarnings("unchecked")
List<Map<String, Serializable>> blobs = (List<Map<String, Serializable>>) doc.getPropertyValue("mb:blobs");
blobs.add(blobProp);
doc.setPropertyValue("mb:blobs", (Serializable) blobs);
}
@Test
public void itCanAccessBlobsThroughBlobHolder() throws Exception {
DocumentModel doc = getTestBlob();
BlobHolder bh = doc.getAdapter(BlobHolder.class);
bh.setBlob(Blobs.createBlob("main"));
doc = session.saveDocument(doc);
TransactionHelper.commitOrRollbackTransaction();
TransactionHelper.startTransaction();
// When i call the rest api
ClientResponse response = getResponse(RequestType.GET, "path" + doc.getPathAsString() + "/@blob/blobholder:0");
// Then i receive the content of the blob
assertEquals(Status.OK.getStatusCode(), response.getStatus());
assertEquals("main", response.getEntity(String.class));
response = getResponse(RequestType.GET, "path" + doc.getPathAsString() + "/@blob/blobholder:1");
assertEquals(Status.OK.getStatusCode(), response.getStatus());
assertEquals("one", response.getEntity(String.class));
response = getResponse(RequestType.GET, "path" + doc.getPathAsString() + "/@blob/blobholder:2");
assertEquals(Status.OK.getStatusCode(), response.getStatus());
assertEquals("two", response.getEntity(String.class));
}
}