/*
* 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.jcr2spi.xml;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import javax.jcr.ImportUUIDBehavior;
import javax.jcr.Item;
import javax.jcr.Property;
import javax.jcr.PropertyType;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.nodetype.ConstraintViolationException;
import javax.jcr.nodetype.NodeType;
import javax.jcr.nodetype.NodeTypeIterator;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.spi.Name;
import org.apache.jackrabbit.test.AbstractJCRTest;
import org.apache.jackrabbit.test.NotExecutableException;
import org.xml.sax.ContentHandler;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.AttributesImpl;
/**
* <code>SessionImportTest</code>...
*/
public class SessionImportTest extends AbstractJCRTest {
@Override
protected void setUp() throws Exception {
super.setUp();
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
public void testImportNameValueWithUnregisteredNamespace() throws RepositoryException, SAXException {
String prefix = getUniquePrefix(superuser);
String uri = getUnknownURI(superuser, "anyURI");
String testValue = prefix + ":someLocalName";
String svuri = Name.NS_SV_URI;
String svprefix = Name.NS_SV_PREFIX + ":";
ContentHandler ch = superuser.getImportContentHandler(testRootNode.getPath(), ImportUUIDBehavior.IMPORT_UUID_CREATE_NEW);
ch.startDocument();
ch.startPrefixMapping(prefix, uri);
String nN = "node";
AttributesImpl attrs = new AttributesImpl();
attrs.addAttribute(svuri, "name", svprefix + "name", "CDATA", nodeName1);
ch.startElement(svuri, nN, svprefix + nN, attrs);
// primary node type
String pN = "property";
attrs = new AttributesImpl();
attrs.addAttribute(svuri, "name", svprefix + "name", "CDATA", JcrConstants.JCR_PRIMARYTYPE);
attrs.addAttribute(svuri, "type", svprefix + "type", "CDATA", PropertyType.nameFromValue(PropertyType.NAME));
ch.startElement(svuri, pN, svprefix + pN, attrs);
ch.startElement(svuri, "value", svprefix + "value", new AttributesImpl());
char[] val = testNodeType.toCharArray();
ch.characters(val, 0, val.length);
ch.endElement(svuri, "value", svprefix + "value");
ch.endElement(svuri, pN, prefix + pN);
// another name value
attrs = new AttributesImpl();
attrs.addAttribute(svuri, "name", svprefix + "name", "CDATA", propertyName1);
attrs.addAttribute(svuri, "type", svprefix + "type", "CDATA", PropertyType.nameFromValue(PropertyType.NAME));
ch.startElement(svuri, pN, svprefix + pN, attrs);
ch.startElement(svuri, "value", svprefix + "value", new AttributesImpl());
val = testValue.toCharArray();
ch.characters(val, 0, val.length);
ch.endElement(svuri, "value", svprefix + "value");
ch.endElement(svuri, pN, svprefix + pN);
ch.endElement(svuri, nN, svprefix + nN);
ch.endDocument();
// test if property has been imported with correct namespace
String assignedPrefix = superuser.getNamespacePrefix(uri);
assertTrue(superuser.getNamespaceURI(assignedPrefix).equals(uri));
String path = testRootNode.getPath() + "/" + nodeName1 + "/" + propertyName1;
assertTrue(superuser.itemExists(path));
Item item = superuser.getItem(path);
if (item.isNode()) {
fail("Item with path " + path + " must be a property.");
} else {
Property prop = (Property) item;
assertTrue(prop.getValue().getType() == PropertyType.NAME);
String expectedValue = assignedPrefix + ":someLocalName";
assertTrue(prop.getValue().getString().equals(expectedValue));
}
// try to save
superuser.save();
}
/**
* Test case for issue <a href="https://issues.apache.org/jira/browse/JCR-1857">JCR-1857</href>
*
* @throws IOException
* @throws RepositoryException
*/
public void testEmptyMixins() throws IOException, RepositoryException {
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<sv:node xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\"\n" +
" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\"\n" +
" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\"\n" +
" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\"\n" +
" sv:name=\"testnode1\">\n" +
" <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\">\n" +
" <sv:value>nt:unstructured</sv:value>\n" +
" </sv:property>\n" +
" <sv:property sv:name=\"jcr:title\" sv:type=\"String\">\n" +
" <sv:value>Test Node</sv:value>\n" +
" </sv:property>\n" +
" <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\">\n" +
" <sv:value>1234</sv:value>\n" +
" </sv:property>\n" +
"</sv:node>";
InputStream in = new ByteArrayInputStream(xml.getBytes());
try {
superuser.importXML(testRootNode.getPath(), in, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
fail("jcr:uuid cannot be created if mix:referenceable is not part of the effective nodetype.");
} catch (ConstraintViolationException e) {
// ok.
}
}
/**
* Test case for issue <a href="https://issues.apache.org/jira/browse/JCR-1857">JCR-1857</href>
*
* @throws IOException
* @throws RepositoryException
*/
public void testEmptyMixins2() throws IOException, RepositoryException, NotExecutableException {
/*
look for a a node type that includes mix:referenceable but isn't any
of the known internal nodetypes that ev. cannot be created through a
session-import
*/
String referenceableNt = null;
NodeTypeIterator it = superuser.getWorkspace().getNodeTypeManager().getPrimaryNodeTypes();
while (it.hasNext() && referenceableNt == null) {
NodeType nt = it.nextNodeType();
String ntName = nt.getName();
if (nt.isNodeType(mixReferenceable) &&
!nt.isAbstract() &&
// TODO: improve....
// ignore are built-in nodetypes (mostly version related)
!ntName.startsWith("nt:") &&
// also skip all internal node types...
!ntName.startsWith("rep:")) {
referenceableNt = ntName;
}
}
if (referenceableNt == null) {
throw new NotExecutableException("No primary type found that extends from mix:referenceable.");
}
/*
TODO: retrieve valid jcr:uuid value from test-properties.
*/
String uuid = UUID.randomUUID().toString();
String xml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" +
"<sv:node xmlns:nt=\"http://www.jcp.org/jcr/nt/1.0\"\n" +
" xmlns:sv=\"http://www.jcp.org/jcr/sv/1.0\"\n" +
" xmlns:mix=\"http://www.jcp.org/jcr/mix/1.0\"\n" +
" xmlns:jcr=\"http://www.jcp.org/jcr/1.0\"\n" +
" sv:name=\"testnode1\">\n" +
" <sv:property sv:name=\"jcr:primaryType\" sv:type=\"Name\">\n" +
" <sv:value>" + referenceableNt + "</sv:value>\n" +
" </sv:property>\n" +
" <sv:property sv:name=\"jcr:uuid\" sv:type=\"String\">\n" +
" <sv:value>" + uuid + "</sv:value>\n" +
" </sv:property>\n" +
"</sv:node>";
InputStream in = new ByteArrayInputStream(xml.getBytes());
superuser.importXML(testRootNode.getPath(), in, ImportUUIDBehavior.IMPORT_UUID_COLLISION_THROW);
}
private static String getUnknownURI(Session session, String uriHint) throws RepositoryException {
String uri = uriHint;
int index = 0;
List<String> uris = Arrays.asList(session.getWorkspace().getNamespaceRegistry().getURIs());
while (uris.contains(uri)) {
uri = uriHint + index;
index++;
}
return uri;
}
/**
* Returns a prefix that is unique among the already registered prefixes.
*
* @param session
* @return a unique prefix
*/
public static String getUniquePrefix(Session session) throws RepositoryException {
return "_pre" + (session.getNamespacePrefixes().length + 1);
}
}