org.apache.jackrabbit.test.api.DocumentViewImportTest Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.jackrabbit.test.api;
import org.apache.jackrabbit.test.NotExecutableException;
import org.xml.sax.SAXException;
import javax.jcr.RepositoryException;
import javax.jcr.Property;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.PropertyType;
import javax.jcr.PropertyIterator;
import javax.jcr.NamespaceException;
import javax.jcr.ImportUUIDBehavior;
import javax.jcr.ItemExistsException;
import javax.jcr.nodetype.ConstraintViolationException;
import java.io.IOException;
/**
* DocumentViewImportTest
Tests importXML and
* getImportContentHandler methods of the Workspace and Session class. Also
* tests the UuidBehaviour flag.
*
*/
public class DocumentViewImportTest extends AbstractImportXmlTest {
private String JCR_XMLTEXT;
private String JCR_XMLCHAR;
private boolean withHandler;
private boolean withWorkspace;
public void setUp() throws Exception {
super.setUp();
JCR_XMLTEXT = superuser.getNamespacePrefix(NS_JCR_URI) + ":xmltext";
JCR_XMLCHAR = superuser.getNamespacePrefix(NS_JCR_URI) + ":xmlcharacters";
}
public void tearDown() throws Exception {
file.delete();
super.tearDown();
}
public void testWorkspaceImportXml() throws Exception {
withHandler = false;
withWorkspace = WORKSPACE;
doTestImportXML();
}
public void testSessionImportXml() throws Exception {
withHandler = false;
withWorkspace = SESSION;
doTestImportXML();
}
public void testWorkspaceGetImportContentHandler() throws Exception {
withHandler = true;
withWorkspace = SESSION;
doTestGetImportContentHandler();
}
public void testSessionGetImportContentHandler() throws Exception {
withHandler = true;
withWorkspace = WORKSPACE;
doTestGetImportContentHandler();
}
/**
* Tests importXML method with uuidBehaviour IMPORT_UUID_CREATE_NEW. It
* imports the document created with createSimpleDocument method and checks
* the imported tree according the rules outlined in chapter 7.3.2 of the
* specification.
*
* Additionally it checks the uuidBehaviour flag if the jcr:uuid property is
* respected during import.
*
* @throws RepositoryException
* @throws IOException
* @throws SAXException
* @throws NotExecutableException
*/
public void doTestImportXML() throws Exception {
importXML(target, createSimpleDocument(), uuidBehaviour, withWorkspace);
// some implementations may require a refresh to get content
// added diretly to the workspace
if (withWorkspace) {
session.refresh(false);
}
performTests();
}
/**
* Tests getImportContentHandler method with uuidBehaviour
* IMPORT_UUID_CREATE_NEW. It imports the document created with
* createSimpleDocument method and checks the imported tree according the
* rules outlined in chapter 7.3.2 of the specification.
*
* Additionally it checks the uuidBehaviour flag if the jcr:uuid property is
* respected during import.
*
* @throws RepositoryException
* @throws SAXException
* @throws IOException
* @throws NotExecutableException
*/
public void doTestGetImportContentHandler() throws Exception {
importWithHandler(target, createSimpleDocument(), uuidBehaviour, withWorkspace);
// some implementations may require a refresh to get content
// added diretly to the workspace
if (withWorkspace) {
session.refresh(false);
}
performTests();
}
private void performTests() throws Exception {
checkImportSimpleXMLTree();
checkNamespaceAdded();
if (!respectMixRef) {
throw new NotExecutableException("ImportXML tests with " +
"uuidBehaviour flag not executable.");
} else {
checkImportDocumentView_IMPORT_UUID_CREATE_NEW();
checkImportDocumentView_IMPORT_UUID_COLLISION_REMOVE_EXISTING();
checkImportDocumentView_IMPORT_UUID_COLLISION_REPLACE_EXISTING();
checkImportDocumentView_IMPORT_UUID_COLLISION_THROW();
}
}
/**
* Tests if the simple xml document defined in createSimpleDocument() is
* imported correctly according the specification rules given in 7.3.2
*/
public void checkImportSimpleXMLTree() throws RepositoryException, IOException {
Node parent = (Node) session.getItem(target);
try {
// check the node names
String prefix = session.getNamespacePrefix(unusedURI);
String rootName = prefix + ":" + rootElem;
//String rootName = rootElem;
Node rootNode = parent.getNode(rootName);
Node child = rootNode.getNode(childElem);
Node xmlTextNode = rootNode.getNode(xmltextElem);
Node grandChild = xmlTextNode.getNode(grandChildElem);
// check xmltext
checkXmlTextNode(xmlTextNode);
// check the property names and values
Property prop = grandChild.getProperty(attributeName);
Property prop2 = xmlTextNode.getProperty(attributeName);
String value = prop.getString();
String value2 = prop2.getString();
assertEquals("Value " + attributeValue + " of attribute " +
attributeName + " is imported to different property values.", value, value2);
assertEquals("Value " + attributeValue + " of attribute " +
attributeName + " is not correctly imported.", value, attributeValue);
// check the encoded names and values
Property decodedProp;
// is decoded
try {
child.getNode(decodedElemName);
decodedProp = child.getProperty(decodedAttributeName);
String propVal = decodedProp.getString();
// both possibilities
if (!propVal.equals(encodedAttributeValue)
&& !propVal.equals(decodedAttributeValue)) {
fail("Value " + encodedAttributeValue + " of attribute " +
decodedAttributeName + " is not correctly imported.");
}
} catch (PathNotFoundException pnfe) {
try {
// is not decoded
child.getNode(encodedElemName);
decodedProp = child.getProperty(encodedAttributeName);
String propVal = decodedProp.getString();
// both possibilities
if (!propVal.equals(encodedAttributeValue)
&& !propVal.equals(decodedAttributeValue)) {
fail("Value " + encodedAttributeValue + " of attribute " +
encodedAttributeName + " is not correctly imported.");
}
} catch (PathNotFoundException pnfe2) {
fail("XML Element " + encodedElemName + " or attribute "
+ encodedAttributeName + " not imported: " + pnfe2);
}
}
} catch (PathNotFoundException pne) {
fail("Element or attribute is not imported: " + pne);
}
}
/**
* Tests if xmltext in a body of a xml element is correctly imported to a
* node with name jcr:xmltext and that the value of the text is stored in
* the singlevalued jcr:xmlcharacters property of String type.
*
* @throws RepositoryException
*/
public void checkXmlTextNode(Node node) throws RepositoryException, IOException {
if (node.hasNode(JCR_XMLTEXT)) {
Node xmlNode = node.getNode(JCR_XMLTEXT);
if (xmlNode.hasProperty(JCR_XMLCHAR)) {
Property prop = xmlNode.getProperty(JCR_XMLCHAR);
// correct type?
assertTrue("Property " + prop.getPath() + " is not of type String.",
prop.getType() == PropertyType.STRING);
// correct text?
// todo remove the trim as only the white spaces of the current text should be collected
assertEquals("Xml text is not correctly stored.",
xmltext.trim(), prop.getString().trim());
// only jcr:xmlcharacters property beneath the jcr:primaryType
PropertyIterator iter = xmlNode.getProperties();
assertTrue(JCR_XMLCHAR + " is not the only property beneath " +
jcrPrimaryType + " in a " + JCR_XMLTEXT + " node.", getSize(iter) == 2);
} else {
fail("Xmltext not stored in property named " + JCR_XMLCHAR);
}
} else {
fail("Xmltext not imported to Node named " + JCR_XMLTEXT);
}
}
/**
* Checks if a namespace not yet existing in the repository is registered
* after an according document import.
*
* @throws RepositoryException
* @throws IOException
*/
public void checkNamespaceAdded() throws RepositoryException, IOException {
try {
assertEquals("URI not correctly imported.", nsp.getURI(unusedPrefix), unusedURI);
assertEquals("Prefix not correctly imported", nsp.getPrefix(unusedURI), unusedPrefix);
} catch (NamespaceException nse) {
fail("Namespace " + unusedPrefix + ":" + unusedURI +
" not imported during document view import.");
}
}
//------------------< uuid collision behaviour tests >--------------------------
// we create a node named referenced below the testRootNode, also we create a xml
// document with an element named rootElem having the uuid of the referenced node
// as attribute and we import this document below the refTargetNode.
/**
* Checks {@link ImportUUIDBehavior#IMPORT_UUID_CREATE_NEW} i.e. that a node
* receives a new uuid when imported in any case.
*/
public void checkImportDocumentView_IMPORT_UUID_CREATE_NEW() throws Exception {
String uuid = createReferenceableNode(referenced);
// import a document with a element having the same uuid as the node referenced
importRefNodeDocument(refTarget, uuid, ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW, withWorkspace, withHandler);
// different uuid?
Node node = refTargetNode.getNode(rootElem);
String rootElemUUID = node.getUUID();
assertFalse("Imported node " + rootElem + " has a UUID which is " +
"yet assigned to another node", uuid.equals(rootElemUUID));
}
/**
* Checks ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING i.e that
* the existing node is removed in case of uuid collision.
*/
public void checkImportDocumentView_IMPORT_UUID_COLLISION_REMOVE_EXISTING()
throws Exception {
String uuid = createReferenceableNode(referenced);
// import a document with a element having the same uuid as the node referenced
importRefNodeDocument(refTarget, uuid, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING,
withWorkspace, withHandler);
try {
// should be removed now
testRootNode.getNode(referenced);
fail("UUID behavior IMPORT_UUID_COLLISION_REMOVE_EXISTING test is failed: " +
"existing node not removed");
} catch (PathNotFoundException pnfe) {
// ok
}
try {
// should be there
refTargetNode.getNode(rootElem);
} catch (PathNotFoundException pnfe) {
fail("UUID behavior IMPORT_UUID_COLLISION_REMOVE_EXISTING test is failed: " +
"imported node not in its correct place.");
}
}
/**
* Checks ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING i.e that
* the existing node is replaced by the imported one node when uuid
* collision occurs.
*/
public void checkImportDocumentView_IMPORT_UUID_COLLISION_REPLACE_EXISTING()
throws Exception {
String uuid = createReferenceableNode(referenced);
// import a document with a element having the same uuid as the node referenced
importRefNodeDocument(refTarget, uuid, ImportUUIDBehavior.IMPORT_UUID_COLLISION_REPLACE_EXISTING,
withWorkspace, withHandler);
// should be replaced i.e should be modified, in case Workspace method is used
// we cannot decide unless we have some additional property of the imported node.
if (!withWorkspace) {
Node node = testRootNode.getNode(rootElem);
assertTrue("Node " + node.getPath() + " not replaced during " +
"import with IMPORT_UUID_COLLISION_REPLACE_EXISTING", node.hasProperty(propertyName1));
}
}
/**
* Checks ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW i.e that a
* ItemExistsException is thrown in case of importing with an input stream
* or a SAXException is thrown in case of importing with a ContentHandler.
*
* @throws RepositoryException
* @throws IOException
*/
public void checkImportDocumentView_IMPORT_UUID_COLLISION_THROW()
throws Exception {
String uuid = createReferenceableNode(referenced);
try {
importRefNodeDocument(refTarget, uuid, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW,
withWorkspace, withHandler);
fail("UUID behavior IMPORT_UUID_COLLISION_THROW test is failed: " +
"should throw an Exception.");
} catch (ItemExistsException e) {
if (!withHandler) {
// ok
} else {
throw e;
}
} catch (SAXException e) {
if (withHandler) {
// ok
} else {
throw e;
}
}
}
//-------------------------------< exception tests >--------------------------------------
/**
* Tests correct failure of importing a element wit the same UUID as the target node or
* an ancestor of it in case of uuidBehavior IMPORT_UUID_COLLISION_REMOVE_EXISTING.
*
* The imported document contains a element with jcr:uuid attribute the same as the
* parent of the import target.
*/
public void doTestSameUUIDAtAncestor(boolean withWorkspace, boolean withHandler)
throws Exception {
String uuid = createReferenceableNode(referenced);
Node node = testRootNode.getNode(referenced);
Node node2 = node.addNode("newParent");
session.save();
// import a document with a element having the same uuid as the node referenced
try {
importRefNodeDocument(node2.getPath(), uuid,
ImportUUIDBehavior.IMPORT_UUID_COLLISION_REMOVE_EXISTING,
withWorkspace, withHandler);
fail("UUID collision with an ancestor of the target node hould throw a " +
"SAXException or a ConstraintViolationException in case of " +
"uuidBehavior IMPORT_UUID_COLLISION_REMOVE_EXISTING.");
} catch(SAXException se) {
if (!withHandler) {
throw se;
}
// ok
} catch (ConstraintViolationException cve) {
if (withHandler) {
throw cve;
}
// ok
}
}
public void testSameUUIDAtAncestorWorkspaceHandler() throws Exception {
doTestSameUUIDAtAncestor(WORKSPACE, CONTENTHANDLER);
}
public void testSameUUIDAtAncestorWorkspace() throws Exception {
doTestSameUUIDAtAncestor(WORKSPACE, STREAM);
}
public void testSameUUIDAtAncestorSessionHandler() throws Exception {
doTestSameUUIDAtAncestor(SESSION, CONTENTHANDLER);
}
public void testSameUUIDAtAncestorSession() throws Exception {
doTestSameUUIDAtAncestor(SESSION, STREAM);
}
}