/** * Copyright (C) 2010 eXo Platform SAS. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.xcmis.restatom; import junit.framework.AssertionFailedError; import junit.framework.TestCase; import org.apache.abdera.Abdera; import org.apache.abdera.factory.Factory; import org.everrest.core.ContainerResponseWriter; import org.everrest.core.RequestHandler; import org.everrest.core.ResourceBinder; import org.everrest.core.impl.ApplicationPublisher; import org.everrest.core.impl.ContainerResponse; import org.everrest.core.impl.EnvironmentContext; import org.everrest.core.impl.ProviderBinder; import org.everrest.core.impl.RequestHandlerImpl; import org.everrest.core.impl.ResourceBinderImpl; import org.everrest.core.impl.SimpleDependencySupplier; import org.everrest.core.tools.DummyContainerResponseWriter; import org.everrest.core.tools.DummySecurityContext; import org.everrest.core.tools.ResourceLauncher; import org.everrest.test.mock.MockHttpServletRequest; import org.everrest.test.mock.MockPrincipal; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xcmis.restatom.abdera.CMISExtensionFactory; import org.xcmis.spi.CmisConstants; import org.xcmis.spi.CmisRegistry; import org.xcmis.spi.Connection; import org.xcmis.spi.ConstraintException; import org.xcmis.spi.ContentStream; import org.xcmis.spi.FilterNotValidException; import org.xcmis.spi.ItemsList; import org.xcmis.spi.ObjectNotFoundException; import org.xcmis.spi.UserContext; import org.xcmis.spi.model.BaseType; import org.xcmis.spi.model.CmisObject; import org.xcmis.spi.model.ObjectParent; import org.xcmis.spi.model.Property; import org.xcmis.spi.model.VersioningState; import org.xcmis.spi.model.impl.IdProperty; import org.xcmis.spi.model.impl.StringProperty; import org.xcmis.spi.utils.Logger; import java.io.ByteArrayInputStream; import java.security.Principal; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import javax.servlet.http.HttpServletRequest; import javax.ws.rs.core.SecurityContext; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathExpressionException; import javax.xml.xpath.XPathFactory; /** * @author <a href="mailto:andrey.parfonov@exoplatform.com">Andrey Parfonov</a> * @version $Id: BaseTest.java 2 2010-02-04 17:21:49Z andrew00x $ */ public abstract class BaseTest extends TestCase { protected final Logger LOG = Logger.getLogger(BaseTest.class); protected String cmisRepositoryId = "cmis1"; protected final String testFolderName = "testRoot"; protected String rootFolderId; protected Factory factory; protected String testFolderId; protected XPath xp; protected Connection conn; protected ResourceLauncher launcher; @Override public void setUp() throws Exception { Abdera abdera = new Abdera(); factory = abdera.getFactory(); factory.registerExtension(new CMISExtensionFactory()); UserContext ctx = new UserContext("root"); UserContext.setCurrent(ctx); conn = CmisRegistry.getInstance().getConnection(cmisRepositoryId); rootFolderId = conn.getStorage().getRepositoryInfo().getRootFolderId(); Map<String, Property<?>> props = new HashMap<String, Property<?>>(); IdProperty propId = new IdProperty(); propId.setId(CmisConstants.OBJECT_TYPE_ID); propId.setLocalName(CmisConstants.OBJECT_TYPE_ID); propId.getValues().add(BaseType.FOLDER.value()); StringProperty propName = new StringProperty(); propName.setId(CmisConstants.NAME); propName.setLocalName(CmisConstants.NAME); propName.getValues().add(testFolderName); props.put(propId.getId(), propId); props.put(propName.getId(), propName); testFolderId = conn.createFolder(rootFolderId, props, null, null, null); xp = XPathFactory.newInstance().newXPath(); xp.setNamespaceContext(new NamespaceResolver()); ResourceBinder resources = new ResourceBinderImpl(); ApplicationPublisher publisher = new ApplicationPublisher(resources, ProviderBinder.getInstance()); publisher.publish(new CmisRestApplication()); SimpleDependencySupplier dependencies = new SimpleDependencySupplier(); ProviderImpl provider = new ProviderImpl(); provider.init(AbderaFactory.getInstance(), new HashMap<String, String>()); dependencies.put(ProviderImpl.class, provider); RequestHandler requestHandler = new RequestHandlerImpl(resources, dependencies); launcher = new ResourceLauncher(requestHandler); } @Override public void tearDown() throws Exception { factory = null; clearRepository(); conn.close(); super.tearDown(); } private void clearRepository() { try { for(CmisObject item : conn.getChildren(rootFolderId, true, null, true, true, "", "", "", 10, 0).getItems()) { if(item.getObjectInfo().getBaseType().equals(BaseType.FOLDER)) { conn.deleteTree(item.getObjectInfo().getId(), true, null, true); } else if(item.getObjectInfo().getBaseType().equals(BaseType.DOCUMENT)) { conn.deleteObject(item.getObjectInfo().getId(), true); } } } catch (Exception e) { e.printStackTrace(); } } protected ContainerResponse service(String method, String requestURI, String baseURI, Map<String, List<String>> headers, byte[] data, ContainerResponseWriter writer) throws Exception { EnvironmentContext envctx = new EnvironmentContext(); ByteArrayInputStream in = null; if (data != null) { in = new ByteArrayInputStream(data); } MockHttpServletRequest httpRequest = new MockHttpServletRequest(requestURI, in, in != null ? in.available() : 0, method, headers); envctx.put(HttpServletRequest.class, httpRequest); Principal adminPrincipal = new MockPrincipal("admin"); Set<String> adminRoles = new HashSet<String>(); adminRoles.add("users"); adminRoles.add("administrators"); envctx.put(SecurityContext.class, new DummySecurityContext(adminPrincipal, adminRoles)); return launcher.service(method, requestURI, baseURI, headers, data, writer, envctx); } protected ContainerResponse service(String method, String requestURI, String baseURI, Map<String, List<String>> headers, byte[] data) throws Exception { return service(method, requestURI, baseURI, headers, data, new DummyContainerResponseWriter()); } protected void validateAllowableActions(org.w3c.dom.Node actions) throws XPathExpressionException { assertEquals(1, countElements("cmis:canDeleteObject", actions)); assertEquals(1, countElements("cmis:canUpdateProperties", actions)); assertEquals(1, countElements("cmis:canGetFolderTree", actions)); assertEquals(1, countElements("cmis:canGetProperties", actions)); assertEquals(1, countElements("cmis:canGetObjectRelationships", actions)); assertEquals(1, countElements("cmis:canGetObjectParents", actions)); assertEquals(1, countElements("cmis:canGetFolderParent", actions)); assertEquals(1, countElements("cmis:canGetDescendants", actions)); assertEquals(1, countElements("cmis:canMoveObject", actions)); assertEquals(1, countElements("cmis:canDeleteContentStream", actions)); assertEquals(1, countElements("cmis:canCheckOut", actions)); assertEquals(1, countElements("cmis:canCancelCheckOut", actions)); assertEquals(1, countElements("cmis:canCheckIn", actions)); assertEquals(1, countElements("cmis:canSetContentStream", actions)); assertEquals(1, countElements("cmis:canGetAllVersions", actions)); assertEquals(1, countElements("cmis:canAddObjectToFolder", actions)); assertEquals(1, countElements("cmis:canRemoveObjectFromFolder", actions)); assertEquals(1, countElements("cmis:canGetContentStream", actions)); assertEquals(1, countElements("cmis:canApplyPolicy", actions)); assertEquals(1, countElements("cmis:canGetAppliedPolicies", actions)); assertEquals(1, countElements("cmis:canRemovePolicy", actions)); assertEquals(1, countElements("cmis:canGetChildren", actions)); assertEquals(1, countElements("cmis:canCreateDocument", actions)); assertEquals(1, countElements("cmis:canCreateFolder", actions)); assertEquals(1, countElements("cmis:canCreateRelationship", actions)); // assertEquals(1, countElements("cmis:canCreatePolicy", xmlDoc)); assertEquals(1, countElements("cmis:canDeleteTree", actions)); assertEquals(1, countElements("cmis:canGetRenditions", actions)); assertEquals(1, countElements("cmis:canGetACL", actions)); assertEquals(1, countElements("cmis:canApplyACL", actions)); } protected void checkTree(org.w3c.dom.Node node, Map<String, List<String>> expected) throws Exception { org.w3c.dom.Node childrenNode = getNode("cmisra:children", node); String id = getNodeValueWithNodeProperty("cmisra:object/cmis:properties", "cmis:propertyId", "cmis:objectId", node); if (childrenNode == null) { if (expected.get(id) == null || expected.get(id).size() == 0) { return; } // If tag 'cmisra:children' not found but Map contains List<String> for current id. fail("Expected children " + expected.get(id) + " not found for object " + id); } List<String> expectedChildren = expected.get(id); org.w3c.dom.NodeList entries = getNodeSet("atom:entry", childrenNode); int length = entries.getLength(); if (length < expectedChildren.size()) { fail("Expected children " + expectedChildren + " not found for object " + id); } for (int i = 0; i < length; i++) { org.w3c.dom.Node child = entries.item(i); String childId = getNodeValueWithNodeProperty("cmisra:object/cmis:properties", "cmis:propertyId", "cmis:objectId", child); if (expectedChildren == null || expectedChildren.size() == 0 || !expectedChildren.contains(childId)) { fail("Unexpected child " + childId + " found for object " + id); } checkTree(child, expected); } } protected int countElements(String expression, org.w3c.dom.Node xmlDoc) throws XPathExpressionException { assertNotNull(xmlDoc); String count = (String)xp.evaluate("count(" + expression + ")", xmlDoc, XPathConstants.STRING); return Integer.parseInt(count); } protected String createDocument(String parent, String name, VersioningState versioningState, ContentStream content) throws Exception { Map<String, Property<?>> properties = new HashMap<String, Property<?>>(); // OBJECT_TYPE_ID String typeId = CmisConstants.DOCUMENT; IdProperty typeIdProperty = new IdProperty(); typeIdProperty.setId(CmisConstants.OBJECT_TYPE_ID); typeIdProperty.setLocalName(CmisConstants.OBJECT_TYPE_ID); typeIdProperty.getValues().add(typeId); properties.put(typeIdProperty.getId(), typeIdProperty); // NAME StringProperty nameProperty = new StringProperty(); nameProperty.setId(CmisConstants.NAME); nameProperty.setLocalName(CmisConstants.NAME); nameProperty.getValues().add(name); properties.put(nameProperty.getId(), nameProperty); // Create Document String objectId = conn.createDocument(parent, properties, content, null, null, null, versioningState); return objectId; } protected String createFolder(String parent, String name) throws Exception { Map<String, Property<?>> properties = new HashMap<String, Property<?>>(); // OBJECT_TYPE_ID String typeId = CmisConstants.FOLDER; IdProperty typeIdProperty = new IdProperty(); typeIdProperty.setId(CmisConstants.OBJECT_TYPE_ID); typeIdProperty.setLocalName(CmisConstants.OBJECT_TYPE_ID); typeIdProperty.getValues().add(typeId); properties.put(typeIdProperty.getId(), typeIdProperty); // NAME StringProperty nameProperty = new StringProperty(); nameProperty.setId(CmisConstants.NAME); nameProperty.setLocalName(CmisConstants.NAME); nameProperty.getValues().add(name); properties.put(nameProperty.getId(), nameProperty); // Create Folder String folderId = conn.createFolder(parent, properties, null, null, null); return folderId; } protected String createPolicy(String parent, String name, String policyText) throws Exception { Map<String, Property<?>> properties = new HashMap<String, Property<?>>(); // OBJECT_TYPE_ID String typeId = CmisConstants.POLICY; IdProperty typeIdProperty = new IdProperty(); typeIdProperty.setId(CmisConstants.OBJECT_TYPE_ID); typeIdProperty.setLocalName(CmisConstants.OBJECT_TYPE_ID); typeIdProperty.getValues().add(typeId); properties.put(typeIdProperty.getId(), typeIdProperty); // NAME StringProperty nameProperty = new StringProperty(); nameProperty.setId(CmisConstants.NAME); nameProperty.setLocalName(CmisConstants.NAME); nameProperty.getValues().add(name); properties.put(nameProperty.getId(), nameProperty); // POLICY_TEXT StringProperty policyTextProperty = new StringProperty(); policyTextProperty.setId(CmisConstants.POLICY_TEXT); policyTextProperty.setLocalName(CmisConstants.POLICY_TEXT); policyTextProperty.getValues().add(name); properties.put(policyTextProperty.getId(), policyTextProperty); // Create Folder String policyId = conn.createPolicy(parent, properties, null, null, null); return policyId; } protected String getAttributeValue(String statement, String attributeName, org.w3c.dom.Document xmlDoc) throws XPathExpressionException { assertNotNull(xmlDoc); org.w3c.dom.Node node = (org.w3c.dom.Node)xp.evaluate(statement, xmlDoc, XPathConstants.NODE); String attr = node.getAttributes().getNamedItem(attributeName).getNodeValue(); return attr; } protected org.w3c.dom.Node getNode(String expression, Node node) throws XPathExpressionException { assertNotNull(node); return (org.w3c.dom.Node)xp.evaluate(expression, node, XPathConstants.NODE); } protected NodeList getNodeSet(String expression, org.w3c.dom.Node xmlDoc) throws XPathExpressionException { assertNotNull(xmlDoc); return (NodeList)xp.evaluate(expression, xmlDoc, XPathConstants.NODESET); } protected String getNodeValueWithNodeProperty(String statement, String propertyType, String property, org.w3c.dom.Node xmlDoc) throws XPathExpressionException { return getStringElement(statement + "/" + propertyType + "[@" + "propertyDefinitionId" + "='" + property + "']/cmis:value", xmlDoc); } protected String getObjectId(CmisObject object) { return object.getObjectInfo().getId(); } protected CmisObject getCmisObject(String objectId) throws ObjectNotFoundException, FilterNotValidException { return conn.getObject(objectId, false, null, false, false, true, CmisConstants.WILDCARD, null); } protected List<ObjectParent> getParents(String id) throws ObjectNotFoundException, FilterNotValidException, ConstraintException { return conn.getObjectParents(id, false, null, false, true, CmisConstants.WILDCARD, null); } protected ItemsList<CmisObject> getChildren(String folderId) throws ObjectNotFoundException, FilterNotValidException { return conn.getChildren(folderId, false, null, false, true, CmisConstants.WILDCARD, null, null, -1, 0); } protected Property<?> getProperty(CmisObject object, String propertyName) { Collection<Property<?>> properties = object.getProperties().values(); if (properties != null) { for (Property<?> prop : properties) { if (prop.getDisplayName().equals(propertyName)) { return prop; } } } return null; } protected String getStringElement(String expression, org.w3c.dom.Node xmlNode) throws XPathExpressionException { assertNotNull(xmlNode); return (String)xp.evaluate(expression, xmlNode, XPathConstants.STRING); } protected boolean hasElementValue(String expression, org.w3c.dom.Node xmlElement) throws XPathExpressionException { assertNotNull(xmlElement); String s = (String)xp.evaluate(expression, xmlElement, XPathConstants.STRING); return s != null && s.length() > 0; } protected boolean hasLink(String relValue, org.w3c.dom.Node xmlElement) throws XPathExpressionException { return hasNodeWithProperty("atom:link", "rel", relValue, xmlElement); } protected boolean hasNodeWithProperty(String statement, String propertyName, String propertyValue, org.w3c.dom.Node xmlElement) throws XPathExpressionException { assertNotNull(xmlElement); org.w3c.dom.Node nodeProperty = (org.w3c.dom.Node)xp.evaluate(statement + "[@" + propertyName + "='" + propertyValue + "']", xmlElement, XPathConstants.NODE); return (nodeProperty != null && nodeProperty.getNodeName() != null); } protected void printBody(byte[] bytes) { System.out.println("+++\n" + new String(bytes) + "\n+++\n"); } protected void validateEntryCommons(org.w3c.dom.Node xmlEntry) throws XPathExpressionException { String[] expected = new String[]{ // "atom:id", // "atom:published", // "atom:updated", // /*"atom:summary",*/// "atom:author", // "atom:author/atom:name", // "atom:title" // }; for (String el : expected) { try { assertTrue("Not found xml element '" + el + "'", hasElementValue(el, xmlEntry)); } catch (AssertionFailedError e) { String elNew = el.substring("atom:".length()); assertTrue("Not found xml element '" + elNew + "'", hasElementValue(elNew, xmlEntry)); } } } protected void validateFeedCommons(org.w3c.dom.Node xmlFeed) throws XPathExpressionException { String[] expected = new String[]{ // "atom:id", // "atom:updated", // "atom:author", // "atom:title" // }; for (String el : expected) { assertTrue("Not found xml element " + el, hasElementValue(el, xmlFeed)); } } protected void validateObjectEntry(org.w3c.dom.Node xmlEntry, String objectType) throws XPathExpressionException { validateEntryCommons(xmlEntry); assertTrue(hasLink(AtomCMIS.LINK_SERVICE, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_EDIT, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_SELF, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_DESCRIBEDBY, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_ALLOWABLEACTIONS, xmlEntry)); if (objectType.equalsIgnoreCase("cmis:folder")) { assertTrue(hasLink(AtomCMIS.LINK_DOWN, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_FOLDERTREE, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_RELATIONSHIPS, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_POLICIES, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_ACL, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_UP, xmlEntry)); } else if (objectType.equalsIgnoreCase("cmis:document")) { assertTrue(hasLink(AtomCMIS.LINK_CMIS_RELATIONSHIPS, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_POLICIES, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_ACL, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CURRENT_VERSION, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_VERSION_HISTORY, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_UP, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_EDIT_MEDIA, xmlEntry)); } else if (objectType.equalsIgnoreCase("cmis:policy")) { assertTrue(hasLink(AtomCMIS.LINK_CMIS_RELATIONSHIPS, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_POLICIES, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_ACL, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_UP, xmlEntry)); } else if (objectType.equalsIgnoreCase("cmis:relationship")) { assertTrue(hasLink(AtomCMIS.LINK_CMIS_SOURCE, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_CMIS_TARGET, xmlEntry)); } // TODO : properties } protected void validateTypeEntry(org.w3c.dom.Node xmlEntry) throws XPathExpressionException { validateEntryCommons(xmlEntry); assertTrue(hasLink(AtomCMIS.LINK_SERVICE, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_SELF, xmlEntry)); assertTrue(hasLink(AtomCMIS.LINK_DOWN, xmlEntry)); // TODO : check links for not root types org.w3c.dom.Node xmlType = getNode("cmisra:type", xmlEntry); assertTrue("Not found 'cmis:id' element", hasElementValue("cmis:id", xmlType)); // assertTrue("Not found 'cmis:displayName' element", hasElementValue("cmis:displayName", xmlDoc)); assertTrue("Not found 'cmis:queryName' element", hasElementValue("cmis:queryName", xmlType)); assertTrue("Not found 'cmis:baseId' element", hasElementValue("cmis:baseId", xmlType)); assertTrue("Not found 'cmis:creatable' element", hasElementValue("cmis:creatable", xmlType)); assertTrue("Not found 'cmis:fileable' element", hasElementValue("cmis:fileable", xmlType)); assertTrue("Not found 'cmis:queryable' element", hasElementValue("cmis:queryable", xmlType)); assertTrue("Not found 'cmis:fulltextIndexed' element", hasElementValue("cmis:fulltextIndexed", xmlType)); assertTrue("Not found 'cmis:includedInSupertypeQuery' element", hasElementValue("cmis:includedInSupertypeQuery", xmlType)); assertTrue("Not found 'cmis:controllableACL' element", hasElementValue("cmis:controllableACL", xmlType)); assertTrue("Not found 'cmis:controllablePolicy' element", hasElementValue("cmis:controllablePolicy", xmlType)); String baseId = getStringElement("cmis:baseId", xmlType); if (baseId.equals("cmis:document")) { assertTrue("Not found 'cmis:versionable' element", hasElementValue("cmis:versionable", xmlType)); assertTrue("Not found 'cmis:contentStreamAllowed' element", hasElementValue("cmis:contentStreamAllowed", xmlType)); } // TODO : property-definitions } }