Java tutorial
/* * Copyright (c) 2006-2011 Nuxeo SA (http://nuxeo.com/) and others. * * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * Florent Guillaume */ package org.nuxeo.ecm.core.opencmis.impl; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.Serializable; import java.math.BigInteger; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletResponse; import org.apache.chemistry.opencmis.client.api.CmisObject; import org.apache.chemistry.opencmis.client.api.Document; import org.apache.chemistry.opencmis.client.api.Folder; import org.apache.chemistry.opencmis.client.api.ItemIterable; import org.apache.chemistry.opencmis.client.api.ObjectId; import org.apache.chemistry.opencmis.client.api.OperationContext; import org.apache.chemistry.opencmis.client.api.Policy; import org.apache.chemistry.opencmis.client.api.Property; import org.apache.chemistry.opencmis.client.api.QueryResult; import org.apache.chemistry.opencmis.client.api.Relationship; import org.apache.chemistry.opencmis.client.api.Rendition; import org.apache.chemistry.opencmis.client.api.Session; import org.apache.chemistry.opencmis.commons.PropertyIds; import org.apache.chemistry.opencmis.commons.data.Ace; import org.apache.chemistry.opencmis.commons.data.AllowableActions; import org.apache.chemistry.opencmis.commons.data.ContentStream; import org.apache.chemistry.opencmis.commons.data.RenditionData; import org.apache.chemistry.opencmis.commons.data.RepositoryInfo; import org.apache.chemistry.opencmis.commons.enums.Action; import org.apache.chemistry.opencmis.commons.enums.RelationshipDirection; import org.apache.chemistry.opencmis.commons.enums.VersioningState; import org.apache.chemistry.opencmis.commons.exceptions.CmisConstraintException; import org.apache.chemistry.opencmis.commons.exceptions.CmisInvalidArgumentException; import org.apache.chemistry.opencmis.commons.exceptions.CmisObjectNotFoundException; import org.apache.chemistry.opencmis.commons.impl.Base64; import org.apache.chemistry.opencmis.commons.impl.dataobjects.ContentStreamImpl; import org.apache.commons.io.IOUtils; import org.apache.http.HttpResponse; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.nuxeo.ecm.core.api.ClientException; import org.nuxeo.ecm.core.api.CoreSession; import org.nuxeo.ecm.core.api.IdRef; import org.nuxeo.ecm.core.api.Lock; import org.nuxeo.ecm.core.api.NuxeoPrincipal; import org.nuxeo.ecm.core.opencmis.impl.client.NuxeoSession; import org.nuxeo.ecm.core.opencmis.impl.server.NuxeoRepositories; import org.nuxeo.ecm.core.opencmis.tests.Helper; import org.nuxeo.ecm.core.storage.sql.SQLRepositoryTestCase; import org.nuxeo.ecm.platform.usermanager.NuxeoPrincipalImpl; /** * Tests that hit the high-level Session abstraction. */ public abstract class NuxeoSessionTestCase extends SQLRepositoryTestCase { public static final String BASE_RESOURCE = "jetty-test"; public static final String NUXEO_ROOT_TYPE = "Root"; // from Nuxeo public static final String NUXEO_ROOT_NAME = ""; // NuxeoPropertyDataName; public static final String USERNAME = "Administrator"; public static final String PASSWORD = "test"; // stream content with non-ASCII characters public static final String STREAM_CONTENT = "Caf\u00e9 Diem\none\0two"; public static final String NOT_NULL = "CONSTRAINT_NOT_NULL"; protected Session session; protected String rootFolderId; protected boolean isAtomPub; protected boolean isBrowser; protected Map<String, String> repoDetails; @Override @Before public void setUp() throws Exception { super.setUp(); // deployed for fulltext indexing deployBundle("org.nuxeo.ecm.core.convert.api"); deployBundle("org.nuxeo.ecm.core.convert"); deployBundle("org.nuxeo.ecm.core.convert.plugins"); // MyDocType deployBundle("org.nuxeo.ecm.core.opencmis.tests"); // MIME Type Icon Updater for renditions deployBundle("org.nuxeo.ecm.platform.mimetype.api"); deployBundle("org.nuxeo.ecm.platform.mimetype.core"); deployBundle("org.nuxeo.ecm.platform.filemanager.api"); deployBundle("org.nuxeo.ecm.platform.filemanager.core"); deployBundle("org.nuxeo.ecm.platform.filemanager.core.listener"); // Rendition Service deployBundle("org.nuxeo.ecm.platform.rendition.api"); deployBundle("org.nuxeo.ecm.platform.rendition.core"); deployBundle("org.nuxeo.ecm.automation.core"); // Audit Service deployBundle("org.nuxeo.ecm.core.persistence"); deployBundle("org.nuxeo.ecm.platform.audit.api"); deployBundle("org.nuxeo.ecm.platform.audit"); deployContrib("org.nuxeo.ecm.core.opencmis.tests.tests", "OSGI-INF/audit-persistence-config.xml"); // QueryMaker registration deployBundle("org.nuxeo.ecm.core.opencmis.impl"); // these deployments needed for NuxeoAuthenticationFilter.loginAs deployBundle("org.nuxeo.ecm.directory.types.contrib"); deployBundle("org.nuxeo.ecm.platform.login"); deployBundle("org.nuxeo.ecm.platform.web.common"); openSession(); // nuxeo setUpCmisSession(); setUpData(); RepositoryInfo rid = session.getBinding().getRepositoryService().getRepositoryInfo(getRepositoryId(), null); assertNotNull(rid); rootFolderId = rid.getRootFolderId(); assertNotNull(rootFolderId); isAtomPub = this instanceof TestNuxeoSessionAtomPub; isBrowser = this instanceof TestNuxeoSessionBrowser; } @Override @After public void tearDown() throws Exception { tearDownData(); tearDownCmisSession(); NuxeoRepositories.clear(); closeSession(); super.tearDown(); } /** Sets up the client, fills "session". */ public abstract void setUpCmisSession() throws Exception; /** Sets up the client, fills "session". */ protected abstract void setUpCmisSession(String username) throws Exception; /** Tears down the client. */ public abstract void tearDownCmisSession() throws Exception; protected void setUpData() throws Exception { repoDetails = Helper.makeNuxeoRepository(super.session); } protected void tearDownData() { } protected CoreSession getCoreSession() { return super.session; } protected String getRepositoryId() { return super.session.getRepositoryName(); } protected String getRootFolderId() { try { return super.session.getRootDocument().getId(); } catch (ClientException e) { throw new RuntimeException(e); } } @Test public void testRoot() { Folder root = session.getRootFolder(); assertNotNull(root); assertNotNull(root.getId()); assertNotNull(root.getType()); assertEquals(NUXEO_ROOT_TYPE, root.getType().getId()); assertEquals(rootFolderId, root.getPropertyValue(PropertyIds.OBJECT_ID)); assertEquals(NUXEO_ROOT_TYPE, root.getPropertyValue(PropertyIds.OBJECT_TYPE_ID)); assertEquals(NUXEO_ROOT_NAME, root.getName()); List<Property<?>> props = root.getProperties(); assertNotNull(props); assertTrue(props.size() > 0); assertEquals("/", root.getPath()); assertEquals(Collections.singletonList("/"), root.getPaths()); assertNull(root.getFolderParent()); assertEquals(Collections.emptyList(), root.getParents()); } @Test public void testDefaultProperties() throws Exception { Folder root = session.getRootFolder(); CmisObject child = root.getChildren().iterator().next(); assertNotNull(child.getProperty("dc:coverage")); assertNull(child.getPropertyValue("dc:coverage")); Document doc = (Document) session.getObjectByPath("/testfolder1/testfile1"); List<String> subjects = doc.getPropertyValue("dc:subjects"); assertEquals(Arrays.asList("foo", "gee/moo"), subjects); } @Test public void testPath() throws Exception { Folder folder = (Folder) session.getObjectByPath("/testfolder1"); assertEquals("/testfolder1", folder.getPath()); assertEquals(Collections.singletonList("/testfolder1"), folder.getPaths()); Document doc = (Document) session.getObjectByPath("/testfolder1/testfile1"); assertEquals(Collections.singletonList("/testfolder1/testfile1"), doc.getPaths()); } @Test public void testParent() throws Exception { Folder folder = (Folder) session.getObjectByPath("/testfolder1"); assertEquals(rootFolderId, folder.getFolderParent().getId()); List<Folder> parents = folder.getParents(); assertEquals(1, parents.size()); assertEquals(rootFolderId, parents.get(0).getId()); Document doc = (Document) session.getObjectByPath("/testfolder1/testfile1"); parents = doc.getParents(); assertEquals(1, parents.size()); assertEquals(folder.getId(), parents.get(0).getId()); } @Test public void testCreateObject() { Folder root = session.getRootFolder(); ContentStream contentStream = null; VersioningState versioningState = null; List<Policy> policies = null; List<Ace> addAces = null; List<Ace> removeAces = null; OperationContext context = NuxeoSession.DEFAULT_CONTEXT; Map<String, Serializable> properties = new HashMap<String, Serializable>(); properties.put(PropertyIds.OBJECT_TYPE_ID, "Note"); properties.put(PropertyIds.NAME, "mynote"); properties.put("note", "bla bla"); Document doc = root.createDocument(properties, contentStream, versioningState, policies, addAces, removeAces, context); assertNotNull(doc.getId()); assertEquals("mynote", doc.getName()); assertEquals("mynote", doc.getPropertyValue("dc:title")); assertEquals("bla bla", doc.getPropertyValue("note")); // list children ItemIterable<CmisObject> children = root.getChildren(); assertEquals(3, children.getTotalNumItems()); CmisObject note = null; for (CmisObject child : children) { if (child.getName().equals("mynote")) { note = child; } } assertNotNull("Missing child", note); assertEquals("Note", note.getType().getId()); assertEquals("bla bla", note.getPropertyValue("note")); } @Test public void testCreateDocumentWithContentStream() throws Exception { Folder root = session.getRootFolder(); ContentStream cs = new ContentStreamImpl("myfile", "text/plain", Helper.FILE1_CONTENT); OperationContext context = NuxeoSession.DEFAULT_CONTEXT; VersioningState versioningState = null; List<Policy> policies = null; List<Ace> addAces = null; List<Ace> removeAces = null; Map<String, Serializable> properties = new HashMap<String, Serializable>(); properties.put(PropertyIds.OBJECT_TYPE_ID, "File"); properties.put(PropertyIds.NAME, "myfile"); Document doc = root.createDocument(properties, cs, versioningState, policies, addAces, removeAces, context); cs = doc.getContentStream(); assertNotNull(cs); assertEquals("text/plain", cs.getMimeType()); assertEquals("myfile", cs.getFileName()); if (!(isAtomPub || isBrowser)) { assertEquals(Helper.FILE1_CONTENT.length(), cs.getLength()); } assertEquals(Helper.FILE1_CONTENT, Helper.read(cs.getStream(), "UTF-8")); } @Test public void testCreateDocumentThenSetContentStream() throws Exception { Folder root = session.getRootFolder(); OperationContext context = NuxeoSession.DEFAULT_CONTEXT; VersioningState versioningState = null; List<Policy> policies = null; List<Ace> addAces = null; List<Ace> removeAces = null; Map<String, Serializable> properties = new HashMap<String, Serializable>(); properties.put(PropertyIds.OBJECT_TYPE_ID, "File"); properties.put(PropertyIds.NAME, "myfile"); Document doc = root.createDocument(properties, null, versioningState, policies, addAces, removeAces, context); ContentStream cs = new ContentStreamImpl("myfile", "text/plain", Helper.FILE1_CONTENT); doc.setContentStream(cs, true); cs = doc.getContentStream(); assertNotNull(cs); assertEquals("text/plain", cs.getMimeType()); assertEquals("myfile", cs.getFileName()); if (!(isAtomPub || isBrowser)) { assertEquals(Helper.FILE1_CONTENT.length(), cs.getLength()); } assertEquals(Helper.FILE1_CONTENT, Helper.read(cs.getStream(), "UTF-8")); } @Test public void testCreateRelationship() throws Exception { String id1 = session.getObjectByPath("/testfolder1/testfile1").getId(); String id2 = session.getObjectByPath("/testfolder1/testfile2").getId(); Map<String, Serializable> properties = new HashMap<String, Serializable>(); properties.put(PropertyIds.OBJECT_TYPE_ID, "Relation"); properties.put(PropertyIds.NAME, "rel"); properties.put(PropertyIds.SOURCE_ID, id1); properties.put(PropertyIds.TARGET_ID, id2); ObjectId relid = session.createRelationship(properties); // note: has to be an administrator to get relations closeSession(); NuxeoPrincipal admin = new NuxeoPrincipalImpl("admin", false, true); super.session = openSessionAs(admin); tearDownCmisSession(); Thread.sleep(1000); // otherwise sometimes fails to set up again // for tests, server-side TrustingLoginProvider makes "admin*" an admin setUpCmisSession(admin.getName()); session.clear(); // clear cache ItemIterable<Relationship> rels = session.getRelationships(session.createObjectId(id1), false, RelationshipDirection.SOURCE, null, session.createOperationContext()); assertEquals(1, rels.getTotalNumItems()); for (Relationship r : rels) { assertEquals(relid.getId(), r.getId()); } Relationship rel = (Relationship) session.getObject(relid); assertNotNull(rel); assertEquals(id1, rel.getSourceId().getId()); assertEquals(id2, rel.getTargetId().getId()); } @Test public void testUpdate() throws Exception { Document doc; doc = (Document) session.getObjectByPath("/testfolder1/testfile1"); Map<String, Object> map = new HashMap<String, Object>(); map.put("dc:title", "new title"); map.put("dc:subjects", Arrays.asList("a", "b", "c")); doc.updateProperties(map); doc = (Document) session.getObjectByPath("/testfolder1/testfile1"); assertEquals("new title", doc.getPropertyValue("dc:title")); assertEquals(Arrays.asList("a", "b", "c"), doc.getPropertyValue("dc:subjects")); // TODO test transient object API map.clear(); map.put("dc:title", "other title"); map.put("dc:subjects", Arrays.asList("foo")); doc.updateProperties(map); doc.refresh(); // reload assertEquals("other title", doc.getPropertyValue("dc:title")); assertEquals(Arrays.asList("foo"), doc.getPropertyValue("dc:subjects")); } @Test public void testContentStream() throws Exception { Document file = (Document) session.getObjectByPath("/testfolder1/testfile1"); // check ETag header if (isAtomPub || isBrowser) { RepositoryInfo ri = session.getRepositoryInfo(); String uri = ri.getThinClientUri() + ri.getId() + "/"; uri += isAtomPub ? "content?id=" : "root?objectId="; uri += file.getId(); String eTag = file.getPropertyValue("nuxeo:contentStreamDigest"); String encoding = Base64.encodeBytes(new String(USERNAME + ":" + PASSWORD).getBytes()); DefaultHttpClient client = new DefaultHttpClient(); HttpGet request = new HttpGet(uri); request.setHeader("Authorization", "Basic " + encoding); request.setHeader("If-None-Match", eTag); try { HttpResponse response = client.execute(request); assertEquals(HttpServletResponse.SC_NOT_MODIFIED, response.getStatusLine().getStatusCode()); } finally { client.getConnectionManager().shutdown(); } } // get stream ContentStream cs = file.getContentStream(); assertNotNull(cs); assertEquals("text/plain", cs.getMimeType()); assertEquals("testfile.txt", cs.getFileName()); if (!(isAtomPub || isBrowser)) { // TODO fix AtomPub/Browser case where the length is unknown (streaming) assertEquals(Helper.FILE1_CONTENT.length(), cs.getLength()); } assertEquals(Helper.FILE1_CONTENT, Helper.read(cs.getStream(), "UTF-8")); // set stream // TODO convenience constructors for ContentStreamImpl byte[] streamBytes = STREAM_CONTENT.getBytes("UTF-8"); ByteArrayInputStream stream = new ByteArrayInputStream(streamBytes); cs = new ContentStreamImpl("foo.txt", BigInteger.valueOf(streamBytes.length), "text/plain; charset=UTF-8", stream); file.setContentStream(cs, true); // refetch stream file = (Document) session.getObject(file); cs = file.getContentStream(); assertNotNull(cs); // AtomPub lowercases charset -> TODO proper mime type comparison String mimeType = cs.getMimeType().toLowerCase().replace(" ", ""); assertEquals("text/plain;charset=utf-8", mimeType); // TODO fix AtomPub case where the filename is null assertEquals("foo.txt", cs.getFileName()); if (!(isAtomPub || isBrowser)) { // TODO fix AtomPub/Browser case where the length is unknown (streaming) assertEquals(streamBytes.length, cs.getLength()); } assertEquals(STREAM_CONTENT, Helper.read(cs.getStream(), "UTF-8")); // delete file.deleteContentStream(); file.refresh(); assertEquals(null, file.getContentStream()); } @Test public void testAllowableActions() throws Exception { CmisObject ob; AllowableActions aa; Set<Action> expected; ob = session.getObjectByPath("/testfolder1"); aa = ob.getAllowableActions(); assertNotNull(aa); expected = EnumSet.of( // Action.CAN_GET_OBJECT_PARENTS, // Action.CAN_GET_PROPERTIES, // Action.CAN_GET_DESCENDANTS, // Action.CAN_GET_FOLDER_PARENT, // Action.CAN_GET_FOLDER_TREE, // Action.CAN_GET_CHILDREN, // Action.CAN_CREATE_DOCUMENT, // Action.CAN_CREATE_FOLDER, // Action.CAN_CREATE_RELATIONSHIP, // Action.CAN_DELETE_TREE, // Action.CAN_GET_RENDITIONS, // Action.CAN_UPDATE_PROPERTIES, // Action.CAN_MOVE_OBJECT, // Action.CAN_DELETE_OBJECT); assertEquals(expected, aa.getAllowableActions()); ob = session.getObjectByPath("/testfolder1/testfile1"); aa = ob.getAllowableActions(); assertNotNull(aa); expected = EnumSet.of( // Action.CAN_GET_OBJECT_PARENTS, // Action.CAN_GET_PROPERTIES, // Action.CAN_GET_CONTENT_STREAM, // Action.CAN_SET_CONTENT_STREAM, // Action.CAN_DELETE_CONTENT_STREAM, // Action.CAN_UPDATE_PROPERTIES, // Action.CAN_MOVE_OBJECT, // Action.CAN_DELETE_OBJECT, // Action.CAN_ADD_OBJECT_TO_FOLDER, // Action.CAN_REMOVE_OBJECT_FROM_FOLDER, // Action.CAN_GET_RENDITIONS, // Action.CAN_GET_ALL_VERSIONS, // Action.CAN_CANCEL_CHECK_OUT, // Action.CAN_CHECK_IN); assertEquals(expected, aa.getAllowableActions()); String q = "SELECT cmis:objectId FROM cmis:document WHERE cmis:name = 'testfile1_Title'"; OperationContext oc = session.createOperationContext(); oc.setIncludeAllowableActions(true); ItemIterable<QueryResult> results = session.query(q, true, oc); assertEquals(1, results.getTotalNumItems()); aa = results.iterator().next().getAllowableActions(); assertNotNull(aa); assertEquals(expected, aa.getAllowableActions()); } public static final Comparator<RenditionData> RENDITION_CMP = new Comparator<RenditionData>() { @Override public int compare(RenditionData a, RenditionData b) { return a.getStreamId().compareTo(b.getStreamId()); }; }; @Test public void testRenditions() throws Exception { CmisObject ob = session.getObjectByPath("/testfolder1/testfile1"); List<Rendition> renditions = ob.getRenditions(); assertNull(renditions); // no renditions by default with object session.clear(); OperationContext oc = session.createOperationContext(); // oc.setRenditionFilterString("*"); ob = session.getObject(session.createObjectId(ob.getId()), oc); renditions = ob.getRenditions(); assertNull(renditions); // get renditions with object session.clear(); oc = session.createOperationContext(); oc.setRenditionFilterString("*"); ob = session.getObject(session.createObjectId(ob.getId()), oc); renditions = ob.getRenditions(); assertEquals(2, renditions.size()); Collections.sort(renditions, RENDITION_CMP); check(renditions.get(0), true); // get renditions with query String q = "SELECT cmis:objectId FROM cmis:document WHERE cmis:name = 'testfile1_Title'"; ItemIterable<QueryResult> results = session.query(q, true, oc); assertEquals(1, results.getTotalNumItems()); renditions = results.iterator().next().getRenditions(); assertEquals(2, renditions.size()); Collections.sort(renditions, RENDITION_CMP); check(renditions.get(0), false); // no rendition stream, Chemistry deficiency (QueryResultImpl // constructor call to of.convertRendition with null) } private static final int TEXT_PNG_ICON_SIZE = 394; protected void check(Rendition ren, boolean checkStream) { assertEquals("cmis:thumbnail", ren.getKind()); assertEquals("nuxeo:icon", ren.getStreamId()); assertEquals("image/png", ren.getMimeType()); assertEquals("text.png", ren.getTitle()); assertEquals(TEXT_PNG_ICON_SIZE, ren.getLength()); if (checkStream) { // get rendition stream ContentStream cs = ren.getContentStream(); assertEquals("image/png", cs.getMimeType()); assertEquals("text.png", cs.getFileName()); assertEquals(TEXT_PNG_ICON_SIZE, cs.getLength()); } } @Test public void testDeletedInTrash() throws Exception { String file5id = repoDetails.get("file5id"); try { session.getObjectByPath("/testfolder1/testfile5"); fail("file 5 should be in trash"); } catch (CmisObjectNotFoundException e) { // ok } try { session.getObject(session.createObjectId(file5id)); fail("file 5 should be in trash"); } catch (CmisObjectNotFoundException e) { // ok } Folder folder = (Folder) session.getObjectByPath("/testfolder1"); ItemIterable<CmisObject> children = folder.getChildren(); assertEquals(3, children.getTotalNumItems()); for (CmisObject child : children) { if (child.getName().equals("title5")) { fail("file 5 should be in trash"); } } // TODO // String query = // "SELECT cmis:objectId FROM cmis:document WHERE dc:title = 'title5'"; // ItemIterable<QueryResult> col = session.query(query, false); // assertEquals("file 5 should be in trash", 0, col.getTotalNumItems()); // cannot delete folder, has children try { folder.delete(true); fail("Should not be able to delete non-empty folder"); } catch (CmisConstraintException e) { // ok } // test trashed child doesn't block folder delete for (CmisObject child : folder.getChildren()) { child.delete(true); } folder.delete(true); } @Test public void testDelete() throws Exception { Document doc = (Document) session.getObjectByPath("/testfolder1/testfile1"); doc.delete(true); session.clear(); try { session.getObjectByPath("/testfolder1/testfile1"); fail("Document should be deleted"); } catch (CmisObjectNotFoundException e) { // ok } } @Test public void testDeleteTree() throws Exception { Folder folder = (Folder) session.getObjectByPath("/testfolder1"); List<String> failed = folder.deleteTree(true, null, true); assertTrue(failed == null || failed.isEmpty()); session.clear(); try { session.getObjectByPath("/testfolder1"); fail("Folder should be deleted"); } catch (CmisObjectNotFoundException e) { // ok } try { session.getObjectByPath("/testfolder1/testfile1"); fail("Folder should be deleted"); } catch (CmisObjectNotFoundException e) { // ok } folder = (Folder) session.getObjectByPath("/testfolder2"); assertNotNull(folder); } @Test public void testCopy() throws Exception { if (isAtomPub) { // copy not implemented by AtomPub bindings return; } Document doc = (Document) session.getObjectByPath("/testfolder1/testfile1"); assertEquals("testfile1_Title", doc.getPropertyValue("dc:title")); Document copy = doc.copy(session.createObjectId(rootFolderId), Collections.singletonMap("dc:title", "new title"), null, null, null, null, session.getDefaultContext()); assertNotSame(doc.getId(), copy.getId()); assertEquals("new title", copy.getPropertyValue("dc:title")); // copy is also available from the folder Document copy2 = session.getRootFolder().createDocumentFromSource(doc, Collections.singletonMap("dc:title", "other title"), null); assertNotSame(copy.getId(), copy2.getId()); assertNotSame(doc.getId(), copy2.getId()); assertEquals("other title", copy2.getPropertyValue("dc:title")); } @Test public void testMove() throws Exception { Folder folder = (Folder) session.getObjectByPath("/testfolder1"); Document doc = (Document) session.getObjectByPath("/testfolder2/testfolder3/testfile4"); String docId = doc.getId(); // TODO add move(target) convenience method doc.move(doc.getParents().get(0), folder); assertEquals(docId, doc.getId()); session.clear(); try { session.getObjectByPath("/testfolder2/testfolder3/testfile4"); fail("Object should be moved away"); } catch (CmisObjectNotFoundException e) { // ok } Document doc2 = (Document) session.getObjectByPath("/testfolder1/testfile4"); assertEquals(docId, doc2.getId()); } @Test public void testVersioning() throws Exception { CmisObject ob = session.getObjectByPath("/testfolder1/testfile1"); String id = ob.getId(); // checked out checkValue(PropertyIds.IS_LATEST_VERSION, Boolean.FALSE, ob); checkValue(PropertyIds.IS_MAJOR_VERSION, Boolean.FALSE, ob); checkValue(PropertyIds.IS_LATEST_MAJOR_VERSION, Boolean.FALSE, ob); checkValue(PropertyIds.VERSION_LABEL, null, ob); checkValue(PropertyIds.VERSION_SERIES_ID, NOT_NULL, ob); checkValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, Boolean.TRUE, ob); checkValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, id, ob); checkValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, USERNAME, ob); checkValue(PropertyIds.CHECKIN_COMMENT, null, ob); String series = ob.getPropertyValue(PropertyIds.VERSION_SERIES_ID); // check in major -> version 1.0 ObjectId vid = ((Document) ob).checkIn(true, null, null, "comment"); CmisObject ver = session.getObject(vid); checkValue(PropertyIds.IS_LATEST_VERSION, Boolean.TRUE, ver); checkValue(PropertyIds.IS_MAJOR_VERSION, Boolean.TRUE, ver); checkValue(PropertyIds.IS_LATEST_MAJOR_VERSION, Boolean.TRUE, ver); checkValue(PropertyIds.VERSION_LABEL, "1.0", ver); checkValue(PropertyIds.VERSION_SERIES_ID, series, ver); checkValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, Boolean.FALSE, ver); checkValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, null, ver); checkValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, null, ver); checkValue(PropertyIds.CHECKIN_COMMENT, "comment", ver); // look at the checked in document to verify // that CMIS views it as a version session.clear(); // clear cache CmisObject ci = session.getObject(ob); checkValue(PropertyIds.IS_LATEST_VERSION, Boolean.TRUE, ci); checkValue(PropertyIds.IS_MAJOR_VERSION, Boolean.TRUE, ci); checkValue(PropertyIds.IS_LATEST_MAJOR_VERSION, Boolean.TRUE, ci); checkValue(PropertyIds.VERSION_LABEL, "1.0", ci); checkValue(PropertyIds.VERSION_SERIES_ID, series, ci); checkValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, Boolean.FALSE, ci); checkValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, null, ci); checkValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, null, ci); checkValue(PropertyIds.CHECKIN_COMMENT, "comment", ci); // check out ObjectId coid = ((Document) ci).checkOut(); session.clear(); // clear cache CmisObject co = session.getObject(coid); assertEquals(id, coid.getId()); // Nuxeo invariant checkValue(PropertyIds.IS_LATEST_VERSION, Boolean.FALSE, co); checkValue(PropertyIds.IS_MAJOR_VERSION, Boolean.FALSE, co); checkValue(PropertyIds.IS_LATEST_MAJOR_VERSION, Boolean.FALSE, co); checkValue(PropertyIds.VERSION_LABEL, null, co); checkValue(PropertyIds.VERSION_SERIES_ID, series, co); checkValue(PropertyIds.IS_VERSION_SERIES_CHECKED_OUT, Boolean.TRUE, co); checkValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_ID, coid.getId(), co); checkValue(PropertyIds.VERSION_SERIES_CHECKED_OUT_BY, USERNAME, co); checkValue(PropertyIds.CHECKIN_COMMENT, null, co); } @Test public void testVersionBasedLocking() throws Exception { CmisObject ob = session.getObjectByPath("/testfolder1/testfile1"); // implicitly checked out after create - unlocked assertFalse(isDocumentLocked(ob)); ((Document) ob).checkIn(true, null, null, "comment"); // checked in - unlocked assertFalse(isDocumentLocked(ob)); CmisObject ci = session.getObject(ob); ObjectId coid = ((Document) ci).checkOut(); session.clear(); // clear cache CmisObject co = session.getObject(coid); // explicitly checked out - locked assertTrue(isDocumentLocked(co)); ((Document) co).cancelCheckOut(); session.clear(); // clear cache CmisObject cco = session.getObject(ob); // cancelled check out - unlocked assertFalse(isDocumentLocked(cco)); // cannot check out a locked document lockDocument(cco); try { ((Document) cco).checkOut(); fail("Cannot check out a locked document"); } catch (CmisInvalidArgumentException e) { // ok } } @Test public void testDeleteObjectOrCancelCheckOut() throws Exception { // test cancelCheckOut CmisObject ob = session.getObjectByPath("/testfolder1/testfile1"); ((Document) ob).checkIn(true, null, null, "comment"); ((Document) ob).checkOut(); Map<String, Object> map = new HashMap<String, Object>(); map.put("dc:title", "new title"); map.put("dc:subjects", Arrays.asList("a", "b", "c")); ob.updateProperties(map); ((Document) ob).cancelCheckOut(); session.clear(); ob = session.getObjectByPath("/testfolder1/testfile1"); assertFalse("new title".equals(ob.getPropertyValue("dc:title"))); //test deleteObject ob = session.getObjectByPath("/testfolder1/testfile2"); map = new HashMap<String, Object>(); map.put("dc:title", "new title"); map.put("dc:subjects", Arrays.asList("a", "b", "c")); ob.updateProperties(map); ((Document) ob).cancelCheckOut(); session.clear(); try { ob = session.getObjectByPath("/testfolder1/testfile2"); fail("Document should be deleted"); } catch (CmisObjectNotFoundException e) { // ok } } @Test public void testCheckInWithChanges() throws Exception { CmisObject ob = session.getObjectByPath("/testfolder1/testfile1"); // check in with data Map<String, Serializable> props = new HashMap<String, Serializable>(); props.put("dc:title", "newtitle"); byte[] bytes = "foo-bar".getBytes("UTF-8"); ByteArrayInputStream in = new ByteArrayInputStream(bytes); ContentStream cs = session.getObjectFactory().createContentStream("test.pdf", bytes.length, "application/pdf", in); ObjectId vid = ((Document) ob).checkIn(true, props, cs, "comment"); CmisObject ver = session.getObject(vid); checkValue(PropertyIds.IS_LATEST_VERSION, Boolean.TRUE, ver); checkValue(PropertyIds.VERSION_LABEL, "1.0", ver); checkValue(PropertyIds.CHECKIN_COMMENT, "comment", ver); // check changes applied checkValue("dc:title", "newtitle", ver); ContentStream cs2 = ((Document) ver).getContentStream(); assertEquals("application/pdf", cs2.getMimeType()); if (!(isAtomPub || isBrowser)) { assertEquals(bytes.length, cs2.getLength()); assertEquals("test.pdf", cs2.getFileName()); } ByteArrayOutputStream os = new ByteArrayOutputStream(); IOUtils.copy(cs2.getStream(), os); assertEquals("foo-bar", os.toString("UTF-8")); } @Test public void testUserWorkspace() throws ClientException { String wsPath = Helper.createUserWorkspace(getCoreSession(), (isAtomPub || isBrowser) ? USERNAME : "Administrator"); Folder ws = (Folder) session.getObjectByPath(wsPath); assertNotNull(ws); } protected void checkValue(String prop, Object expected, CmisObject ob) { Object value = ob.getPropertyValue(prop); if (expected == NOT_NULL) { assertNotNull(value); } else { assertEquals(expected, value); } } private boolean isDocumentLocked(CmisObject ob) throws ClientException { return getCoreSession().getDocument(new IdRef(ob.getId())).isLocked(); } private Lock lockDocument(CmisObject ob) throws ClientException { return getCoreSession().getDocument(new IdRef(ob.getId())).setLock(); } }