Index: trunk/jackrabbit/project.xml =================================================================== --- trunk/jackrabbit/project.xml (revision 394970) +++ trunk/jackrabbit/project.xml (working copy) @@ -542,6 +542,7 @@ **/*.xml **/*.txt + **/*.cnd Index: trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/test_ns_cnd_nodetypes.cnd =================================================================== --- trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/test_ns_cnd_nodetypes.cnd (revision 0) +++ trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/test_ns_cnd_nodetypes.cnd (revision 0) @@ -0,0 +1,14 @@ + + + +[testns3:emptyNodeType] > nt:base + +[testns4:mixinNodeType] + mixin + +[testns3:orderableNodeType] > nt:base + orderable + +[testns4:itemNodeType] > nt:base + - testns4:myDouble (double) ignore + - testns4:myBool (boolean) protected Index: trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java =================================================================== --- trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java (revision 394970) +++ trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java (working copy) @@ -15,26 +15,36 @@ */ package org.apache.jackrabbit.core.nodetype.xml; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.Arrays; + +import javax.jcr.NamespaceRegistry; +import javax.jcr.PropertyType; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.Session; +import javax.jcr.SimpleCredentials; +import javax.jcr.Workspace; +import javax.jcr.nodetype.NodeTypeManager; +import javax.jcr.version.OnParentVersionAction; + import junit.framework.AssertionFailedError; import junit.framework.TestCase; + +import org.apache.jackrabbit.api.JackrabbitNodeTypeManager; +import org.apache.jackrabbit.core.TransientRepository; import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException; import org.apache.jackrabbit.core.nodetype.NodeDef; import org.apache.jackrabbit.core.nodetype.NodeTypeDef; +import org.apache.jackrabbit.core.nodetype.NodeTypeManagerImpl; import org.apache.jackrabbit.core.nodetype.PropDef; import org.apache.jackrabbit.core.value.InternalValue; import org.apache.jackrabbit.name.NamespaceResolver; import org.apache.jackrabbit.name.QName; -import javax.jcr.NamespaceRegistry; -import javax.jcr.PropertyType; -import javax.jcr.RepositoryException; -import javax.jcr.version.OnParentVersionAction; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.util.Arrays; - /** * Test cases for reading and writing node type definition files. */ @@ -47,6 +57,14 @@ private static final String TEST_NODETYPES = "org/apache/jackrabbit/core/nodetype/xml/test_nodetypes.xml"; + /** Name of the xml nodetype file for import and namespace registration. */ + private static final String TEST_NS_XML_NODETYPES = + "org/apache/jackrabbit/core/nodetype/xml/test_ns_xml_nodetypes.xml"; + + /** Name of the cnd nodetype file for import and namespace registration. */ + private static final String TEST_NS_CND_NODETYPES = + "org/apache/jackrabbit/core/nodetype/xml/test_ns_cnd_nodetypes.cnd"; + /** Test node types definitions. */ private NodeTypeDef[] types; @@ -209,6 +227,35 @@ assertTrue("itemNodeType wildcard property", pdef.definesResidual()); } + /** Test for namespace registration on node type import. */ + public void testImportXMLNodeTypes() throws Exception { + Repository rep = new TransientRepository(); + Session session = rep.login(new SimpleCredentials("user", "password".toCharArray())); + try { + Workspace workspace = session.getWorkspace(); + NodeTypeManager ntm = workspace.getNodeTypeManager(); + ((NodeTypeManagerImpl)ntm).registerNodeTypes(getClass().getClassLoader().getResourceAsStream(TEST_NS_XML_NODETYPES), JackrabbitNodeTypeManager.TEXT_XML); + assertTrue("xml test2 namespace registered", session.getNamespaceURI("testns2") != null); + } finally { + session.logout(); + } + } + + /** Test for namespace registration on node type import. */ + public void testImportCNDNodeTypes() throws Exception { + + Repository rep = new TransientRepository(); + Session session = rep.login(new SimpleCredentials("user", "password".toCharArray())); + Workspace workspace = session.getWorkspace(); + try { + NodeTypeManager ntm = workspace.getNodeTypeManager(); + ((NodeTypeManagerImpl)ntm).registerNodeTypes(getClass().getClassLoader().getResourceAsStream(TEST_NS_CND_NODETYPES), JackrabbitNodeTypeManager.TEXT_X_JCR_CND); + assertTrue("cnd test3 namespace registered", session.getNamespaceURI("testns3") != null); + } finally { + session.logout(); + } + } + /** Test for the empty item definition. */ public void testEmptyItem() { PropDef def = getProperty("itemNodeType", "emptyItem"); Index: trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/test_ns_xml_nodetypes.xml =================================================================== --- trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/test_ns_xml_nodetypes.xml (revision 0) +++ trunk/jackrabbit/src/test/java/org/apache/jackrabbit/core/nodetype/xml/test_ns_xml_nodetypes.xml (revision 0) @@ -0,0 +1,193 @@ + + + + + + + nt:base + + + + + + + + nt:base + + + + + + + nt:base + + + + + + + + + + + + + + + + nt:base + + + + + [0,) + + + + + true + false + + + true + + + + + + [2005-01-01T00:00:00.000Z,2006-01-01T00:00:00.000Z) + + + + 2005-01-01T00:00:00.000Z + + + + + [,0.0) + (1.0,2.0) + (3.0,] + + + 1.5 + + + + + (-10,0] + [1,2] + [10,100) + + + 25 + + + + + testns1:testName + + + testns1:testName + + + + + /testns1:testPath + + + + + bananas? + + + banana + bananas + + + + + + + + nt:base + + + + + + + Index: trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/SessionImpl.java =================================================================== --- trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (revision 394970) +++ trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/SessionImpl.java (working copy) @@ -236,7 +236,7 @@ } this.subject = subject; nsMappings = new LocalNamespaceMappings(rep.getNamespaceRegistry()); - ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), getNamespaceResolver()); + ntMgr = new NodeTypeManagerImpl(rep.getNodeTypeRegistry(), rep.getNamespaceRegistry(), getNamespaceResolver()); String wspName = wspConfig.getName(); wsp = createWorkspaceInstance(wspConfig, rep.getWorkspaceStateManager(wspName), rep, this); Index: trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java =================================================================== --- trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java (revision 394970) +++ trunk/jackrabbit/src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java (working copy) @@ -15,28 +15,6 @@ */ package org.apache.jackrabbit.core.nodetype; -import org.apache.commons.collections.map.ReferenceMap; -import org.apache.jackrabbit.name.IllegalNameException; -import org.apache.jackrabbit.name.NamespaceResolver; -import org.apache.jackrabbit.name.QName; -import org.apache.jackrabbit.name.UnknownPrefixException; -import org.apache.jackrabbit.util.IteratorHelper; -import org.apache.jackrabbit.util.name.NamespaceMapping; -import org.apache.jackrabbit.api.JackrabbitNodeTypeManager; -import org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader; -import org.apache.jackrabbit.core.nodetype.compact.ParseException; -import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader; -import org.apache.jackrabbit.core.util.Dumpable; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; -import org.xml.sax.InputSource; -import org.xml.sax.SAXException; - -import javax.jcr.RepositoryException; -import javax.jcr.nodetype.NoSuchNodeTypeException; -import javax.jcr.nodetype.NodeType; -import javax.jcr.nodetype.NodeTypeIterator; - import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -44,12 +22,38 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.Enumeration; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Properties; import java.util.Set; +import javax.jcr.NamespaceException; +import javax.jcr.NamespaceRegistry; +import javax.jcr.RepositoryException; +import javax.jcr.nodetype.NoSuchNodeTypeException; +import javax.jcr.nodetype.NodeType; +import javax.jcr.nodetype.NodeTypeIterator; + +import org.apache.commons.collections.map.ReferenceMap; +import org.apache.jackrabbit.api.JackrabbitNodeTypeManager; +import org.apache.jackrabbit.core.nodetype.compact.CompactNodeTypeDefReader; +import org.apache.jackrabbit.core.nodetype.compact.ParseException; +import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader; +import org.apache.jackrabbit.core.util.Dumpable; +import org.apache.jackrabbit.name.IllegalNameException; +import org.apache.jackrabbit.name.NamespaceResolver; +import org.apache.jackrabbit.name.QName; +import org.apache.jackrabbit.name.UnknownPrefixException; +import org.apache.jackrabbit.util.IteratorHelper; +import org.apache.jackrabbit.util.name.NamespaceMapping; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.xml.sax.InputSource; +import org.xml.sax.SAXException; + /** * A NodeTypeManagerImpl implements a session dependant * NodeTypeManager. @@ -68,6 +72,11 @@ private final NodeTypeRegistry ntReg; /** + * The wrapped node type registry. + */ + private final NamespaceRegistry nsReg; + + /** * The root node definition. */ private final NodeDefinitionImpl rootNodeDef; @@ -102,7 +111,9 @@ * @param nsResolver namespace resolver */ public NodeTypeManagerImpl(NodeTypeRegistry ntReg, + NamespaceRegistry nsReg, NamespaceResolver nsResolver) { + this.nsReg = nsReg; this.nsResolver = nsResolver; this.ntReg = ntReg; this.ntReg.addListener(this); @@ -327,18 +338,59 @@ } /** + * Registers a single namespace bypassing registration if it is already registered. + * + * @param - The identifier for the namespace + * @param - The unique identifier of the collection in the space + */ + protected void registerNamespace(String prefix, String uri) throws RepositoryException + { + //Check if the uri is already registered + String regPrefix = null; + try { + regPrefix = nsReg.getPrefix(uri); + } catch (NamespaceException ne){ + //The uri was not in the registry so attempt to map the prefix to it. + } + + //The uri is not in the registry. The prefix may be with another uri + // or it may not be (the ideal scenario). In either case, attempt to register it + // and let the registry decide whether what to do in the case of an already existing prefix. + if ((regPrefix == null) || !regPrefix.equals(prefix)) + //Attempt to register the prefix and uri...if the prefix is already registered + //an exception will be thrown due to an attempt to remap. + nsReg.registerNamespace(prefix, uri); + } + + /** * Registers the node types defined in the given XML stream. This * is a trivial implementation that just invokes the existing * {@link NodeTypeReader} and {@link NodeTypeRegistry} methods and - * heuristically creates the returned node type array. + * heuristically creates the returned node type array. It will also register + * any namespaces defined in the input source that have not already been registered. * * {@inheritDoc} */ public NodeType[] registerNodeTypes(InputSource in) throws SAXException, RepositoryException { try { - NodeTypeDef[] defs = NodeTypeReader.read(in.getByteStream()); - return registerNodeTypes(Arrays.asList(defs)); + NodeTypeReader ntr = new NodeTypeReader(in.getByteStream()); + Properties namespaces = ntr.getNamespaces(); + if (namespaces != null){ + Enumeration prefixes = namespaces.propertyNames(); + while (prefixes.hasMoreElements()){ + String prefix = (String) prefixes.nextElement(); + registerNamespace(prefix, namespaces.getProperty(prefix)); + } + } + try { + NodeTypeDef[] defs = ntr.getNodeTypeDefs(); + return registerNodeTypes(Arrays.asList(defs)); + } catch (IllegalNameException ine){ + throw new RepositoryException(ine.getMessage(), ine); + } catch (UnknownPrefixException upe){ + throw new RepositoryException(upe.getMessage(), upe); + } } catch (InvalidNodeTypeDefException e) { throw new RepositoryException("Invalid node type definition", e); } catch (IOException e) { @@ -348,32 +400,44 @@ private static final String APPLICATION_XML = "application/xml"; - /** {@inheritDoc} */ + /** + * Registers the node types defined in the given input stream depending on the + * content type specified for the stream. This will also register any namespaces + * identified in the input stream if they have not already been registered. + * + * {@inheritDoc} + */ public NodeType[] registerNodeTypes(InputStream in, String contentType) - throws IOException, RepositoryException { - try { - if (contentType.equalsIgnoreCase(JackrabbitNodeTypeManager.TEXT_XML) - || contentType.equalsIgnoreCase(APPLICATION_XML)) { - return registerNodeTypes(new InputSource(in)); - } else if (contentType.equalsIgnoreCase( - JackrabbitNodeTypeManager.TEXT_X_JCR_CND)) { - NamespaceMapping mapping = new NamespaceMapping(nsResolver); - CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader( - new InputStreamReader(in), "cnd input stream", mapping); - return registerNodeTypes(reader.getNodeTypeDefs()); - } else { - throw new UnsupportedOperationException( - "Unsupported content type: " + contentType); - } - } catch (InvalidNodeTypeDefException e) { - throw new RepositoryException("Invalid node type definition", e); - } catch (SAXException e) { - throw new IOException(e.getMessage()); - } catch (ParseException e) { - throw new IOException(e.getMessage()); + throws IOException, RepositoryException { + try { + if (contentType.equalsIgnoreCase(JackrabbitNodeTypeManager.TEXT_XML) + || contentType.equalsIgnoreCase(APPLICATION_XML)) { + return registerNodeTypes(new InputSource(in)); + } else if (contentType.equalsIgnoreCase( + JackrabbitNodeTypeManager.TEXT_X_JCR_CND)) { + NamespaceMapping mapping = new NamespaceMapping(nsResolver); + CompactNodeTypeDefReader reader = new CompactNodeTypeDefReader( + new InputStreamReader(in), "cnd input stream", mapping); + Map nsMap = mapping.getPrefixToURIMapping(); + Iterator it = nsMap.keySet().iterator(); + while (it.hasNext()){ + String prefix = (String)it.next(); + registerNamespace(prefix, (String)nsMap.get(prefix)); + } + return registerNodeTypes(reader.getNodeTypeDefs()); + } else { + throw new UnsupportedOperationException( + "Unsupported content type: " + contentType); } - } - + } catch (InvalidNodeTypeDefException e) { + throw new RepositoryException("Invalid node type definition", e); + } catch (SAXException e) { + throw new IOException(e.getMessage()); + } catch (ParseException e) { + throw new IOException(e.getMessage()); + } + } + //-------------------------------------------------------------< Dumpable > /** * {@inheritDoc}