/* * ModeShape (http://www.modeshape.org) * * 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. */ package org.modeshape.connector.cmis; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.InputStream; import java.util.Calendar; import java.util.HashMap; import java.util.Map; import javax.jcr.Binary; import javax.jcr.Node; import javax.jcr.Property; import javax.jcr.PropertyIterator; import javax.jcr.nodetype.NodeType; import javax.jcr.nodetype.NodeTypeIterator; import javax.jcr.nodetype.NodeTypeManager; import javax.jcr.security.AccessControlManager; import javax.jcr.security.AccessControlPolicy; import org.apache.chemistry.opencmis.client.api.Session; import org.apache.chemistry.opencmis.client.api.SessionFactory; import org.apache.chemistry.opencmis.client.runtime.SessionFactoryImpl; import org.apache.chemistry.opencmis.commons.SessionParameter; import org.apache.chemistry.opencmis.commons.enums.BindingType; import org.apache.log4j.Logger; import org.junit.AfterClass; import org.junit.BeforeClass; import org.junit.Test; import org.modeshape.jcr.MultiUseAbstractTest; import org.modeshape.jcr.RepositoryConfiguration; import org.modeshape.jcr.api.Workspace; /** * Provide integration testing of the CMIS connector with OpenCMIS InMemory Repository. * * @author Alexander Voloshyn * @version 1.0 2/20/2013 */ public class CmisConnectorIT extends MultiUseAbstractTest { /** * Test OpenCMIS InMemory Server URL. * <p/> * This OpenCMIS InMemory server instance should be started by maven cargo plugin at pre integration stage. */ private static final String CMIS_URL = "http://localhost:8090/"; private static Logger logger = Logger.getLogger(CmisConnectorIT.class); @BeforeClass public static void beforeAll() throws Exception { // waiting when CMIS repository will be ready boolean isReady = false; // max time for waiting in milliseconds long maxTime = 30000L; // actially waiting time in milliseconds long waitingTime = 0L; // time quant in milliseconds long timeQuant = 500L; logger.info("Waiting for CMIS repository..."); do { try { testDirectChemistryConnect(); isReady = true; } catch (Exception e) { Thread.sleep(timeQuant); waitingTime += timeQuant; } } while (!isReady && waitingTime < maxTime); // checking status if (!isReady) { throw new IllegalStateException("CMIS repository did not respond withing " + maxTime + " milliseconds"); } logger.info("CMIS repository has been started successfuly"); RepositoryConfiguration config = RepositoryConfiguration.read("config/repository-1.json"); startRepository(config); } @AfterClass public static void afterAll() throws Exception { MultiUseAbstractTest.afterAll(); } public static void testDirectChemistryConnect() { // default factory implementation SessionFactory factory = SessionFactoryImpl.newInstance(); Map<String, String> parameter = new HashMap<String, String>(); // connection settings parameter.put(SessionParameter.BINDING_TYPE, BindingType.WEBSERVICES.value()); parameter.put(SessionParameter.WEBSERVICES_ACL_SERVICE, CMIS_URL + "services/ACLService?wsdl"); parameter.put(SessionParameter.WEBSERVICES_DISCOVERY_SERVICE, CMIS_URL + "services/DiscoveryService?wsdl"); parameter.put(SessionParameter.WEBSERVICES_MULTIFILING_SERVICE, CMIS_URL + "services/MultiFilingService?wsdl"); parameter.put(SessionParameter.WEBSERVICES_NAVIGATION_SERVICE, CMIS_URL + "services/NavigationService?wsdl"); parameter.put(SessionParameter.WEBSERVICES_OBJECT_SERVICE, CMIS_URL + "services/ObjectService10?wsdl"); parameter.put(SessionParameter.WEBSERVICES_POLICY_SERVICE, CMIS_URL + "services/PolicyService?wsdl"); parameter.put(SessionParameter.WEBSERVICES_RELATIONSHIP_SERVICE, CMIS_URL + "services/RelationshipService?wsdl"); parameter.put(SessionParameter.WEBSERVICES_REPOSITORY_SERVICE, CMIS_URL + "services/RepositoryService10?wsdl"); parameter.put(SessionParameter.WEBSERVICES_VERSIONING_SERVICE, CMIS_URL + "services/VersioningService?wsdl"); // Default repository id for in memory server is A1 parameter.put(SessionParameter.REPOSITORY_ID, "A1"); // create session final Session session = factory.createSession(parameter); assertTrue("Chemistry session should exists.", session != null); } @Test public void shouldSeeCmisTypesAsJcrTypes() throws Exception { NodeTypeManager manager = getSession().getWorkspace().getNodeTypeManager(); NodeTypeIterator it = manager.getNodeType("nt:file").getDeclaredSubtypes(); while (it.hasNext()) { NodeType nodeType = it.nextNodeType(); assertTrue(nodeType != null); } } @Test public void shouldAccessRootFolder() throws Exception { Node root = getSession().getNode("/cmis"); assertTrue(root != null); } @Test public void testRootFolderName() throws Exception { Node root = getSession().getNode("/cmis"); assertEquals("cmis", root.getName()); } @Test public void shouldAccessRepositoryInfo() throws Exception { Node repoInfo = getSession().getNode("/cmis/repositoryInfo"); // Different Chemistry versions return different things ... assertTrue(repoInfo.getProperty("cmis:productName").getString().contains("OpenCMIS")); assertTrue(repoInfo.getProperty("cmis:productName").getString().contains("InMemory")); assertEquals("Apache Chemistry", repoInfo.getProperty("cmis:vendorName").getString()); assertTrue(repoInfo.getProperty("cmis:productVersion").getString() != null); } @Test public void shouldAccessFolderByPath() throws Exception { Node root = getSession().getNode("/cmis"); assertTrue(root != null); Node node1 = getSession().getNode("/cmis/My_Folder-0-0"); assertTrue(node1 != null); Node node2 = getSession().getNode("/cmis/My_Folder-0-0/My_Folder-1-0"); assertTrue(node2 != null); Node node3 = getSession().getNode("/cmis/My_Folder-0-0/My_Folder-1-0/My_Folder-2-0"); assertTrue(node3 != null); } @Test public void shouldAccessDocumentPath() throws Exception { Node file = getSession().getNode("/cmis/My_Folder-0-0/My_Document-1-0"); assertTrue(file != null); } @Test public void shouldAccessBinaryContent() throws Exception { Node file = getSession().getNode("/cmis/My_Folder-0-0/My_Document-1-0"); Node cnt = file.getNode("jcr:content"); Property value = cnt.getProperty("jcr:data"); Binary bv = value.getValue().getBinary(); InputStream is = bv.getStream(); ByteArrayOutputStream bout = new ByteArrayOutputStream(); int b = 0; while (b != -1) { b = is.read(); if (b != -1) { bout.write(b); } } byte[] content = bout.toByteArray(); String s = new String(content, 0, content.length); assertFalse("Content shouldn't be empty.", s.trim().isEmpty()); } // -----------------------------------------------------------------------/ // Folder cmis build-in properties // -----------------------------------------------------------------------/ @Test public void shouldAccessObjectIdPropertyForFolder() throws Exception { Node node = getSession().getNode("/cmis/My_Folder-0-0"); String objectId = node.getProperty("jcr:uuid").getString(); assertTrue(objectId != null); } @Test public void shouldAccessNamePropertyForFolder() throws Exception { Node node = getSession().getNode("/cmis/My_Folder-0-0"); String name = node.getName(); assertEquals("My_Folder-0-0", name); } @Test public void shouldAccessCreatedByPropertyForFolder() throws Exception { Node node = getSession().getNode("/cmis/My_Folder-0-0"); String name = node.getProperty("jcr:createdBy").getString(); assertEquals("unknown", name); } @Test public void shouldAccessCreationDatePropertyForFolder() throws Exception { Node node = getSession().getNode("/cmis/My_Folder-0-0"); Calendar date = node.getProperty("jcr:created").getDate(); assertTrue(date != null); } @Test public void shouldAccessModificationDatePropertyForFolder() throws Exception { Node node = getSession().getNode("/cmis/My_Folder-0-0"); Calendar date = node.getProperty("jcr:lastModified").getDate(); assertTrue(date != null); } // -----------------------------------------------------------------------/ // Document cmis build-in properties // -----------------------------------------------------------------------/ @Test public void shouldAccessObjectIdPropertyForDocument() throws Exception { Node node = getSession().getNode("/cmis/My_Folder-0-0/My_Document-1-0"); String objectId = node.getProperty("jcr:uuid").getString(); assertTrue(objectId != null); } @Test public void shouldAccessCreatedByPropertyForDocument() throws Exception { Node node = getSession().getNode("/cmis/My_Folder-0-0/My_Document-1-0"); String name = node.getProperty("jcr:createdBy").getString(); assertEquals("unknown", name); } @Test public void shouldAccessCreationDatePropertyForDocument() throws Exception { Node node = getSession().getNode("/cmis/My_Folder-0-0/My_Document-1-0"); Calendar date = node.getProperty("jcr:created").getDate(); assertTrue(date != null); } @Test public void shouldCreateFolderAndDocument() throws Exception { Node root = getSession().getNode("/cmis"); String name = "test" + System.currentTimeMillis(); Node node = root.addNode(name, "nt:folder"); assertTrue(name.equals(node.getName())); // node.setProperty("name", "test-name"); root = getSession().getNode("/cmis/" + name); Node node1 = root.addNode("test-1", "nt:file"); // System.out.println("Test: creating binary content"); byte[] content = "Hello World".getBytes(); ByteArrayInputStream bin = new ByteArrayInputStream(content); bin.reset(); // System.out.println("Test: creating content node"); Node contentNode = node1.addNode("jcr:content", "nt:resource"); Binary binary = session.getValueFactory().createBinary(bin); contentNode.setProperty("jcr:data", binary); contentNode.setProperty("jcr:lastModified", Calendar.getInstance()); getSession().save(); } @Test public void shouldModifyDocument() throws Exception { Node file = getSession().getNode("/cmis/My_Folder-0-0/My_Document-1-0"); PropertyIterator it = file.getProperties(); while (it.hasNext()) { Object val = it.nextProperty(); printMessage("property=>" + val); } file.setProperty("StringProp", "modeshape"); getSession().save(); } @Test public void shouldBeAbleToMoveExternalNodes() throws Exception { assertNotNull(session.getNode("/cmis/My_Folder-0-0/My_Document-1-0")); ((Workspace)session.getWorkspace()).move("/cmis/My_Folder-0-0/My_Document-1-0", "/cmis/My_Folder-0-1/My_Document-1-X"); Node file = session.getNode("/cmis/My_Folder-0-1/My_Document-1-X"); assertNotNull(file); assertNotNull(session.getNode("/cmis/My_Folder-0-0")); ((Workspace)session.getWorkspace()).move("/cmis/My_Folder-0-0", "/cmis/My_Folder-0-X"); Node folder = session.getNode("/cmis/My_Folder-0-X"); assertNotNull(folder); assertEquals("nt:folder", folder.getPrimaryNodeType().getName()); //undo the moves so that the original folder and document are unchaged (they are used by the other tests as well) ((Workspace) session.getWorkspace()).move("/cmis/My_Folder-0-1/My_Document-1-X", "/cmis/My_Folder-0-X/My_Document-1-0"); ((Workspace) session.getWorkspace()).move("/cmis/My_Folder-0-X", "/cmis/My_Folder-0-0"); } @Test public void shouldContainAccessList() throws Exception { AccessControlManager acm = session.getAccessControlManager(); AccessControlPolicy[] policies = acm.getPolicies("/cmis/My_Folder-0-0"); assertEquals(1, policies.length); } }