Index: src/test/java/org/apache/jackrabbit/core/config/testCustomNodeTypes.xml =================================================================== --- src/test/java/org/apache/jackrabbit/core/config/testCustomNodeTypes.xml (revision 0) +++ src/test/java/org/apache/jackrabbit/core/config/testCustomNodeTypes.xml (revision 0) @@ -0,0 +1,18 @@ + + + + + + + + nt:resource + + + + \ No newline at end of file Index: src/test/java/org/apache/jackrabbit/core/config/repository.xml =================================================================== --- src/test/java/org/apache/jackrabbit/core/config/repository.xml (revision 379317) +++ src/test/java/org/apache/jackrabbit/core/config/repository.xml (working copy) @@ -16,11 +16,11 @@ a Security element that specifies the name of the app-entry in the JAAS config and the access manager - a Workspaces element that specifies the location of the - workspaces root directory, the name of the default workspace, - the maximum idle time before a workspace is automatically - shutdown (optional) and the workspace configuration root directory - within the virtual repository file system (optional) + a Workspaces element that specifies the location of the + workspaces root directory, the name of the default workspace, + the maximum idle time before a workspace is automatically + shutdown (optional) and the workspace configuration root directory + within the virtual repository file system (optional) a Workspace element that is used as a workspace configuration template; it is used to create the initial workspace if there's @@ -138,6 +138,16 @@ + + + + ]> @@ -234,4 +244,11 @@ + + + + + Index: src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java =================================================================== --- src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java (revision 379317) +++ src/test/java/org/apache/jackrabbit/core/nodetype/xml/TestAll.java (working copy) @@ -64,7 +64,7 @@ InputStream xml = getClass().getClassLoader().getResourceAsStream(TEST_NODETYPES); - types = NodeTypeReader.read(xml); + types = XmlNodeTypeReader.read(xml); registry = new SimpleNamespaceRegistry(); registry.registerNamespace("test", TEST_NAMESPACE); @@ -501,10 +501,10 @@ public void testWrite() throws IOException, RepositoryException { try { ByteArrayOutputStream xml = new ByteArrayOutputStream(); - NodeTypeWriter.write(xml, types, registry); + XmlNodeTypeWriter.write(xml, types, registry); byte[] bytes = xml.toByteArray(); NodeTypeDef[] output = - NodeTypeReader.read(new ByteArrayInputStream(bytes)); + XmlNodeTypeReader.read(new ByteArrayInputStream(bytes)); assertTrue("write output", Arrays.equals(types, output)); } catch (InvalidNodeTypeDefException e) { fail(e.getMessage()); Index: src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/RepositoryImpl.java (working copy) @@ -30,6 +30,7 @@ import org.apache.jackrabbit.core.fs.FileSystemResource; import org.apache.jackrabbit.core.lock.LockManager; import org.apache.jackrabbit.core.lock.LockManagerImpl; +import org.apache.jackrabbit.core.nodetype.NodeTypeDef; import org.apache.jackrabbit.core.nodetype.NodeTypeImpl; import org.apache.jackrabbit.core.nodetype.NodeTypeRegistry; import org.apache.jackrabbit.core.nodetype.virtual.VirtualNodeTypeStateManager; @@ -220,6 +221,20 @@ // create registries nsReg = createNamespaceRegistry(new BasedFileSystem(repStore, "/namespaces")); ntReg = createNodeTypeRegistry(nsReg, new BasedFileSystem(repStore, "/nodetypes")); + + if (repConfig.getCustomNodeTypeConfig() != null + && !ntReg.hasCustomNodeTypesDefined()) { + try { + NodeTypeDef[] customNodeTypes = + repConfig.getCustomNodeTypeConfig().getCustomNodeTypes(nsReg); + for (int i = 0; i < customNodeTypes.length; i++) { + ntReg.registerNodeType(customNodeTypes[i]); + } + } catch( Exception e ) { + log.error( "An exception occurred while reading the custom node definitions; " + + "they will be ignored.", e ); + } + } // init workspace configs Iterator iter = repConfig.getWorkspaceConfigs().iterator(); Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeManagerImpl.java (working copy) @@ -23,7 +23,7 @@ import org.apache.jackrabbit.name.UnknownPrefixException; import org.apache.jackrabbit.util.IteratorHelper; import org.apache.jackrabbit.api.JackrabbitNodeTypeManager; -import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader; +import org.apache.jackrabbit.core.nodetype.xml.XmlNodeTypeReader; import org.apache.jackrabbit.core.util.Dumpable; import org.apache.log4j.Logger; import org.xml.sax.InputSource; @@ -303,7 +303,7 @@ /** * 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 + * {@link XmlNodeTypeReader} and {@link NodeTypeRegistry} methods and * heuristically creates the returned node type array. * * {@inheritDoc} @@ -311,7 +311,7 @@ public NodeType[] registerNodeTypes(InputSource in) throws SAXException, RepositoryException { try { - NodeTypeDef[] defs = NodeTypeReader.read(in.getByteStream()); + NodeTypeDef[] defs = XmlNodeTypeReader.read(in.getByteStream()); ntReg.registerNodeTypes(Arrays.asList(defs)); Set types = new HashSet(); Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeReader.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeReader.java (revision 0) +++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeReader.java (revision 0) @@ -0,0 +1,51 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.core.nodetype; + +import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException; + +import java.io.IOException; +import java.io.InputStream; +import java.util.Properties; + +/** + * Node type definition reader. This interface defines the contract used to + * read node type definitions. + */ +public interface NodeTypeReader { + + /** + * Reads a node type definition file. The file contents are read + * from the given input stream and the parsed node type definitions + * are returned. + * + * @param in file input stream + * @return node type definitions + * @throws IOException if the node type definitions + * cannot be read + * @throws InvalidNodeTypeDefException if the node type definition + * format is invalid + */ + NodeTypeDef[] readNodeTypes(InputStream in) + throws IOException, InvalidNodeTypeDefException; + + /** + * Returns the namespaces declared in the node type definition + * file. + */ + Properties getNamespaces(); +} Index: src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeWriter.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeWriter.java (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeWriter.java (working copy) @@ -37,6 +37,9 @@ /** * Node type definition writer. This class is used to write the * persistent node type definition files used by Jackrabbit. + * + * @deprecated As of release 1.0. Replaced by + * {@link org.apache.jackrabbit.core.nodetype.xml.XmlNodeTypeWriter}. */ public final class NodeTypeWriter { Index: src/main/java/org/apache/jackrabbit/core/nodetype/xml/XmlNodeTypeWriter.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/nodetype/xml/XmlNodeTypeWriter.java (revision 379284) +++ src/main/java/org/apache/jackrabbit/core/nodetype/xml/XmlNodeTypeWriter.java (working copy) @@ -38,7 +38,7 @@ * Node type definition writer. This class is used to write the * persistent node type definition files used by Jackrabbit. */ -public final class NodeTypeWriter { +public final class XmlNodeTypeWriter { /** * Writes a node type definition file. The file contents are written @@ -57,7 +57,7 @@ OutputStream xml, NodeTypeDef[] types, NamespaceRegistry registry) throws IOException, RepositoryException { try { - NodeTypeWriter writer = new NodeTypeWriter(registry); + XmlNodeTypeWriter writer = new XmlNodeTypeWriter(registry); for (int i = 0; i < types.length; i++) { writer.addNodeTypeDef(types[i]); } @@ -86,7 +86,7 @@ * @throws RepositoryException if the namespace mappings cannot * be retrieved from the registry */ - private NodeTypeWriter(NamespaceRegistry registry) + private XmlNodeTypeWriter(NamespaceRegistry registry) throws ParserConfigurationException, RepositoryException { builder = new DOMBuilder(Constants.NODETYPES_ELEMENT); Index: src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeReader.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeReader.java (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/nodetype/xml/NodeTypeReader.java (working copy) @@ -43,6 +43,9 @@ /** * Node type definition reader. This class is used to read the * persistent node type definition files used by Jackrabbit. + * + * @deprecated As of release 1.0. Replaced by + * {@link org.apache.jackrabbit.core.nodetype.xml.XmlNodeTypeReader}. */ public class NodeTypeReader { Index: src/main/java/org/apache/jackrabbit/core/nodetype/xml/XmlNodeTypeReader.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/nodetype/xml/XmlNodeTypeReader.java (revision 379284) +++ src/main/java/org/apache/jackrabbit/core/nodetype/xml/XmlNodeTypeReader.java (working copy) @@ -22,6 +22,7 @@ import org.apache.jackrabbit.core.nodetype.NodeDef; import org.apache.jackrabbit.core.nodetype.NodeDefImpl; import org.apache.jackrabbit.core.nodetype.NodeTypeDef; +import org.apache.jackrabbit.core.nodetype.NodeTypeReader; import org.apache.jackrabbit.core.nodetype.PropDef; import org.apache.jackrabbit.core.nodetype.PropDefImpl; import org.apache.jackrabbit.core.nodetype.ValueConstraint; @@ -44,7 +45,7 @@ * Node type definition reader. This class is used to read the * persistent node type definition files used by Jackrabbit. */ -public class NodeTypeReader { +public class XmlNodeTypeReader implements NodeTypeReader { /** * Reads a node type definition file. The file contents are read from @@ -60,26 +61,18 @@ */ public static NodeTypeDef[] read(InputStream xml) throws IOException, InvalidNodeTypeDefException { - try { - NodeTypeReader reader = new NodeTypeReader(xml); - return reader.getNodeTypeDefs(); - } catch (IllegalNameException e) { - throw new InvalidNodeTypeDefException( - "Invalid namespace reference in a node type definition", e); - } catch (UnknownPrefixException e) { - throw new InvalidNodeTypeDefException( - "Invalid namespace reference in a node type definition", e); - } + XmlNodeTypeReader reader = new XmlNodeTypeReader(); + return reader.readNodeTypes(xml); } /** The node type document walker. */ - private final DOMWalker walker; + private DOMWalker walker; /** The namespaces associated with the node type XML document. */ - private final Properties namespaces; + private Properties namespaces; /** The namespace resolver. */ - private final NamespaceResolver resolver; + private NamespaceResolver resolver; /** * Creates a node type definition file reader. @@ -87,13 +80,37 @@ * @param xml node type definition file * @throws IOException if the node type definition file cannot be read */ - public NodeTypeReader(InputStream xml) throws IOException { + public XmlNodeTypeReader(InputStream xml) throws IOException { walker = new DOMWalker(xml); namespaces = walker.getNamespaces(); resolver = new AdditionalNamespaceResolver(namespaces); } - + /** + * Creates a node type definition file reader. + */ + public XmlNodeTypeReader() {} + + /** + * {@inheritDoc} + */ + public NodeTypeDef[] readNodeTypes(InputStream in) + throws IOException, InvalidNodeTypeDefException { + try { + walker = new DOMWalker(in); + namespaces = walker.getNamespaces(); + resolver = new AdditionalNamespaceResolver(namespaces); + return getNodeTypeDefs(); + } catch (IllegalNameException e) { + throw new InvalidNodeTypeDefException( + "Invalid namespace reference in a node type definition", e); + } catch (UnknownPrefixException e) { + throw new InvalidNodeTypeDefException( + "Invalid namespace reference in a node type definition", e); + } + } + + /** * Returns the namespaces declared in the node type definition * file. */ Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeRegistry.java (working copy) @@ -1414,6 +1414,29 @@ public synchronized boolean isBuiltIn(QName nodeTypeName) { return builtInNTDefs.contains(nodeTypeName); } + + /** + * Returns true if this node type registry contains custom node types. + * + * @return true if this node type registry contains custom + * node type definitions; false otherwise. + */ + public synchronized boolean hasCustomNodeTypesDefined() + throws RepositoryException { + boolean customNodeTypesDefined = false; + + try { + customNodeTypesDefined = customNodeTypesResource.exists(); + } catch (FileSystemException fse) { + String error = + "internal error: failed to access custom node type definitions stored in " + + customNodeTypesResource.getPath(); + log.debug(error); + throw new RepositoryException(error, fse); + } + + return customNodeTypesDefined; + } /** * @param id Index: src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/nodetype/NodeTypeDefStore.java (working copy) @@ -16,8 +16,8 @@ */ package org.apache.jackrabbit.core.nodetype; -import org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader; -import org.apache.jackrabbit.core.nodetype.xml.NodeTypeWriter; +import org.apache.jackrabbit.core.nodetype.xml.XmlNodeTypeReader; +import org.apache.jackrabbit.core.nodetype.xml.XmlNodeTypeWriter; import org.apache.jackrabbit.name.QName; import javax.jcr.NamespaceRegistry; @@ -52,7 +52,7 @@ public void load(InputStream in) throws IOException, InvalidNodeTypeDefException, RepositoryException { - NodeTypeDef[] types = NodeTypeReader.read(in); + NodeTypeDef[] types = XmlNodeTypeReader.read(in); for (int i = 0; i < types.length; i++) { add(types[i]); } @@ -68,7 +68,7 @@ throws IOException, RepositoryException { NodeTypeDef[] types = (NodeTypeDef[]) ntDefs.values().toArray(new NodeTypeDef[ntDefs.size()]); - NodeTypeWriter.write(out, types, registry); + XmlNodeTypeWriter.write(out, types, registry); } /** Index: src/main/java/org/apache/jackrabbit/core/config/config.dtd =================================================================== --- src/main/java/org/apache/jackrabbit/core/config/config.dtd (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/config/config.dtd (working copy) @@ -154,3 +154,13 @@ + + + + Index: src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/config/RepositoryConfig.java (working copy) @@ -218,6 +218,11 @@ private final SearchConfig sc; /** + * Optional custom node type configuration. + */ + private final CustomNodeTypeConfig cntc; + + /** * Creates a repository configuration object. * * @param template workspace configuration template @@ -232,6 +237,7 @@ * @param defaultWorkspace name of the default workspace * @param vc versioning configuration * @param sc search configuration for system search manager. + * @param cntc custom node type configuration * @param parser the ConfigurationParser that servers as config factory */ public RepositoryConfig(String home, String name, @@ -239,7 +245,7 @@ String workspaceDirectory, String workspaceConfigDirectory, String defaultWorkspace, int workspaceMaxIdleTime, Element template, VersioningConfig vc, SearchConfig sc, - ConfigurationParser parser) { + CustomNodeTypeConfig cntc, ConfigurationParser parser) { this.workspaces = new HashMap(); this.home = home; this.name = name; @@ -253,6 +259,7 @@ this.template = template; this.vc = vc; this.sc = sc; + this.cntc = cntc; this.parser = parser; } @@ -269,6 +276,9 @@ if (sc != null) { sc.init(); } + if (cntc != null) { + cntc.init(); + } // Get the physical workspace root directory (create it if not found) File directory = new File(workspaceDirectory); @@ -657,4 +667,15 @@ public SearchConfig getSearchConfig() { return sc; } + + /** + * Returns the repository custom node type definition configuration. + * Returns null if no custom node type definition file + * has been configured. + * + * @return search index configuration, or null + */ + public CustomNodeTypeConfig getCustomNodeTypeConfig() { + return cntc; + } } Index: src/main/java/org/apache/jackrabbit/core/config/CustomNodeTypeConfig.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/config/CustomNodeTypeConfig.java (revision 0) +++ src/main/java/org/apache/jackrabbit/core/config/CustomNodeTypeConfig.java (revision 0) @@ -0,0 +1,148 @@ +/* + * Copyright 2004-2005 The Apache Software Foundation or its licensors, + * as applicable. + * + * Licensed 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.core.config; + +import javax.jcr.NamespaceRegistry; +import javax.jcr.NamespaceException; +import javax.jcr.RepositoryException; + +import org.apache.jackrabbit.core.nodetype.InvalidNodeTypeDefException; +import org.apache.jackrabbit.core.nodetype.NodeTypeDef; +import org.apache.jackrabbit.core.nodetype.NodeTypeReader; + +import java.io.InputStream; +import java.io.IOException; +import java.util.Enumeration; +import java.util.Properties; + +/** + * Custom node type configuration. This bean configuration class is used + * to create the custom node types in the repository. + */ +public class CustomNodeTypeConfig extends BeanConfig { + + /** + * The name of the custom node type definition file's path property. + */ + private static final String PATH_PROPERTY = "path"; + + /** + * The node type reader implmentation used to process the custom node + * type definition file. + */ + private NodeTypeReader ntr; + + /** + * Creates a custom node type configuration object. + * + * @param readerClassName The name of the class used to process the + * custom node type definition file. + * @param custom node type configuration properties + */ + public CustomNodeTypeConfig( + String readerClassName, Properties properties ) { + super( readerClassName, properties ); + } + + /** + * Creates the custom node type configuration object. + * + * @throws ConfigurationException if the requested type cannot + * be instantiated. + */ + public void init() throws ConfigurationException { + Class nodeTypeReaderClass = null; + + try { + nodeTypeReaderClass = Class.forName( getClassName() ); + } catch (ClassNotFoundException e) { + throw new ConfigurationException( "Could not find " + + getClassName() + ".", e ); + } + + if (!NodeTypeReader.class.isAssignableFrom( nodeTypeReaderClass )) { + throw new ConfigurationException( + getClassName() + " does not implement the " + + "org.apache.jackrabbit.core.nodetype.NodeTypeReader " + + "interface." ); + } + + try { + ntr = (NodeTypeReader) nodeTypeReaderClass.newInstance(); + } catch (Exception e) { + throw new ConfigurationException( + "Could not instantiate" + getClassName() + ".", e ); + } + } + + /** + * Returns an array of NodeTypeDef objects found in the + * custom node type definition file. + * + * @return an array of NodeTypeDef objects + * @throws ConfigurationException if an error occurs while processing + * the custom node type definition file + */ + public NodeTypeDef[] getCustomNodeTypes(NamespaceRegistry nsReg) + throws ConfigurationException { + String nodeTypeDefFileLocation = getParameters().getProperty(PATH_PROPERTY); + + if (nodeTypeDefFileLocation == null) { + throw new ConfigurationException( + "The '" + PATH_PROPERTY + "' property was not found."); + } + + InputStream in = null; + NodeTypeDef[] nodeTypeDefinitions = null; + + try { + in = getClass().getClassLoader().getResourceAsStream(nodeTypeDefFileLocation); + nodeTypeDefinitions = ntr.readNodeTypes(in); + Properties namespaces = ntr.getNamespaces(); + + Enumeration nsEnum = namespaces.propertyNames(); + while (nsEnum.hasMoreElements()) { + String prefix = (String) nsEnum.nextElement(); + try { + nsReg.getURI(prefix); + } catch (NamespaceException e) { + nsReg.registerNamespace(prefix, namespaces.getProperty(prefix)); + } + } + } catch (IOException e) { + throw new ConfigurationException( + "An error occured while reading from " + nodeTypeDefFileLocation + ".", e); + } catch (InvalidNodeTypeDefException e) { + throw new ConfigurationException( + "An invalid node type was found in " + nodeTypeDefFileLocation + ".", e); + } catch (RepositoryException e) { + throw new ConfigurationException( + "A RepositoryException occurred while processing " + + nodeTypeDefFileLocation + ".", e); + } finally { + if (in != null) { + try { + in.close(); + } catch (IOException e) { + // ignore + } + } + } + + return nodeTypeDefinitions; + } +} Index: src/main/java/org/apache/jackrabbit/core/config/ConfigurationParser.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/config/ConfigurationParser.java (revision 379317) +++ src/main/java/org/apache/jackrabbit/core/config/ConfigurationParser.java (working copy) @@ -78,6 +78,10 @@ /** Name of the versioning configuration element. */ public static final String VERSIONING_ELEMENT = "Versioning"; + + /** Name of the custom node type definitions configuration element. */ + public static final String CUSTOM_NODE_TYPE_DEFINITIONS_ELEMENT = + "CustomNodeTypeDefinitions"; /** Name of the file system configuration element. */ public static final String FILE_SYSTEM_ELEMENT = "FileSystem"; @@ -111,6 +115,10 @@ /** Name of the bean implementation class configuration attribute. */ public static final String CLASS_ATTRIBUTE = "class"; + /** Name of the custom node type definition reader implementation + class configuration attribute. */ + public static final String READER_CLASS_ATTRIBUTE = "readerClass"; + /** Name of the bean parameter name configuration attribute. */ public static final String NAME_ATTRIBUTE = "name"; @@ -121,6 +129,11 @@ public static final String DEFAULT_QUERY_HANDLER = "org.apache.jackrabbit.core.query.lucene.SearchIndex"; + /** Name of the default custom node definition reader + implementation class. */ + public static final String DEFAULT_CUSTOM_NODE_TYPE_READER = + "org.apache.jackrabbit.core.nodetype.xml.NodeTypeReader"; + /** * The configuration parser variables. These name-value pairs * are used to substitute ${...} variable references @@ -243,10 +256,13 @@ // Optional search configuration SearchConfig sc = parseSearchConfig(root); + + // Optional custom node type configuration + CustomNodeTypeConfig cntc = parseCustomNodeTypeConfig(root); return new RepositoryConfig(home, appName, amc, lmc, fsc, workspaceDirectory, workspaceConfigDirectory, defaultWorkspace, - maxIdleTime, template, vc, sc, this); + maxIdleTime, template, vc, sc, cntc, this); } /** @@ -378,6 +394,52 @@ } /** + * Parses custom node type configuration. Custom node type configuration + * uses the following format: + *
+     *   <CustomNodeTypeDefinitions class="...">
+     *     <param name="..." value="...">
+     *     ...
+     *   </CustomNodeTypeDefinitions>
+     * 
+ *

+ * The CustomNodeTypeDefinitions elements is a + * {@link #parseBeanConfig(Element,String) bean configuration} element. + * If the custom node type reader implementation class is not given, then + * a default implementation is used. + *

+ * The custom node type configuration is an optional feature of repository + * configuration. If the custom node type configuration element is not + * found, then this method returns null. + *

+ * + * @param parent parent of the CustomNodeTypeDefinitions element + * @return custom node type definitions configuration, or null + * @throws ConfigurationException if the configuration is broken + */ + protected CustomNodeTypeConfig parseCustomNodeTypeConfig(Element parent) + throws ConfigurationException { + NodeList children = parent.getChildNodes(); + for (int i = 0; i < children.getLength(); i++) { + Node child = children.item(i); + if (child.getNodeType() == Node.ELEMENT_NODE + && CUSTOM_NODE_TYPE_DEFINITIONS_ELEMENT.equals(child.getNodeName())) { + Element element = (Element) child; + + // Custom node type reader implementation class + String readerClassName = getAttribute( + element, READER_CLASS_ATTRIBUTE, DEFAULT_CUSTOM_NODE_TYPE_READER); + + // Search parameters + Properties parameters = parseParameters(element); + + return new CustomNodeTypeConfig(readerClassName, parameters); + } + } + return null; + } + + /** * Parses versioning configuration. Versioning configuration uses the * following format: *