/**
* 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
}
}