You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by fm...@apache.org on 2005/12/21 21:18:36 UTC

svn commit: r358365 [3/4] - in /incubator/jackrabbit/trunk/contrib/extension-framework: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/jackrabbit/ src/main/java/org/apache/jackrabbit/extension/ sr...

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/XMLNodeConfiguration.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/XMLNodeConfiguration.java?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/XMLNodeConfiguration.java (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/XMLNodeConfiguration.java Wed Dec 21 12:17:51 2005
@@ -0,0 +1,174 @@
+/*
+ * 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.extension.configuration;
+
+import java.io.File;
+import java.net.URL;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.XMLConfiguration;
+
+/**
+ * The <code>XMLNodeConfiguration</code> extends the Apache Commons
+ * <code>XMLConfiguration</code> by support for loading the XML configuratîon
+ * from a repository property in addition to the standard loading source such as
+ * file, URL, and streams.
+ *
+ * @author Felix Meschberger
+ * @version $Rev:$, $Date$
+ */
+public class XMLNodeConfiguration extends XMLConfiguration implements
+        RepositoryConfiguration {
+
+    /**
+     * The delegate object which takes care for actually loading and saving
+     * configuration to and from the repository.
+     */
+    private final ConfigurationIODelegate delegate =
+        new ConfigurationIODelegate(this);
+
+    {
+        // set the default encoding to UTF-8
+        setEncoding(ConfigurationIODelegate.ENCODING);
+    }
+
+    /**
+     * Creates an empty <code>XMLNodeConfiguration</code> object which can be
+     * used to synthesize a new XML file by adding values and then saving().
+     */
+    public XMLNodeConfiguration() {
+        super();
+    }
+
+    /**
+     * Creates and loads the configuration from the specified file.
+     *
+     * @param fileName The name of the XML file to load.
+     *
+     * @throws ConfigurationException Error while loading the XML file
+     */
+    public XMLNodeConfiguration(String fileName) throws ConfigurationException {
+        super(fileName);
+    }
+
+    /**
+     * Creates and loads the configuration from the specified file.
+     *
+     * @param file The XML file to load.
+     *
+     * @throws ConfigurationException Error while loading the XML file
+     */
+    public XMLNodeConfiguration(File file) throws ConfigurationException {
+        super(file);
+    }
+
+    /**
+     * Creates and loads the configuration from the specified URL
+     *
+     * @param url The location of the XML file to load.
+     *
+     * @throws ConfigurationException Error while loading the XML file
+     */
+    public XMLNodeConfiguration(URL url) throws ConfigurationException {
+        super(url);
+    }
+
+    /**
+     * Creates and loads the configuration from the specified <code>node</code>.
+     *
+     * @param node The <code>Node</code> from which to load the configuration.
+     * @throws ConfigurationException Error while loading the XML file
+     */
+    public XMLNodeConfiguration(javax.jcr.Node node)
+            throws ConfigurationException {
+        super();
+        setNode(node);
+        load();
+    }
+
+    /**
+     * Returns the <code>Node</code> on which this configuration is based. If
+     * this is not a repository-based configuration object or has not been
+     * configured to load from the repository, this method returns
+     * <code>null</code>.
+     */
+    public javax.jcr.Node getNode() {
+        return delegate.getNode();
+    }
+
+    /**
+     * Sets the <code>Node</code> on which this configuration is based.
+     */
+    public void setNode(javax.jcr.Node node) {
+        delegate.setNode(node);
+    }
+
+    /**
+     * Loads the configuration from the underlying location.
+     *
+     * @throws ConfigurationException if loading of the configuration fails
+     */
+    public void load() throws ConfigurationException {
+        delegate.load();
+    }
+
+    /**
+     * Loads the configuration from the <code>node</code>. The property to
+     * use is found following the the node's primary item trail: While the
+     * primary item is a node, the node's primary item is accessed. If it is a
+     * property which is not a reference, the property is returned. If the
+     * property is a reference, the reference is resolved and this step is
+     * repeated.
+     * <p>
+     * If no property can be found using above mentioned algorithm, loading the
+     * configuration fails.
+     *
+     * @param node The <code>Node</code> of the repository based configuration
+     *            to load from.
+     * @throws ConfigurationException if an error occurs during the load
+     *             operation or if no property can be found containing the
+     *             properties "file".
+     */
+    public void load(javax.jcr.Node node) throws ConfigurationException {
+        delegate.load(node);
+    }
+
+    /**
+     * Saves the configuration to the underlying location.
+     *
+     * @throws ConfigurationException if saving of the configuration fails
+     */
+    public void save() throws ConfigurationException {
+        delegate.save();
+    }
+
+    /**
+     * Saves the configuration in the <code>node</code>. The same algorithm
+     * applies for finding the property to store the configuration in as is
+     * applied by the {@link #load(javax.jcr.Node)} method. If no property can
+     * be found saving the configuration fails.
+     *
+     * @param node The <code>Node</code> of the repository based configuration
+     *      to save the configuration in.
+     *
+     * @throws ConfigurationException if an error occurs during the save
+     *      operation.
+     */
+    public void save(javax.jcr.Node node) throws ConfigurationException {
+        delegate.save(node);
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/XMLNodeConfiguration.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/XMLNodeConfiguration.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/package.html
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/package.html?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/package.html (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/package.html Wed Dec 21 12:17:51 2005
@@ -0,0 +1,8 @@
+<body>
+<p>
+This package contains classes and interfaces extending the Jakarta Commons
+Configuration library by support for Repository based configuration where
+the nodes and properties are read from and written to a subtree of the
+repository.
+</p>
+</body>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/configuration/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/package.html
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/package.html?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/package.html (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/package.html Wed Dec 21 12:17:51 2005
@@ -0,0 +1,4 @@
+<body>
+<p>This package contains the Jackrabbit Extension Framework. See the Jackrabbit
+Extension Framework site for an in-depth description.</p>
+</body>

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/java/org/apache/jackrabbit/extension/package.html
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/resources/org/apache/jackrabbit/extension/type.cnd
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/main/resources/org/apache/jackrabbit/extension/type.cnd?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/main/resources/org/apache/jackrabbit/extension/type.cnd (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/main/resources/org/apache/jackrabbit/extension/type.cnd Wed Dec 21 12:17:51 2005
@@ -0,0 +1,30 @@
+/*
+ * The "type.cnd" file contains the (mixin) node type definition which is
+ * required by the ExtensionManager class.
+ *
+ * NOTE: This file is read through a reader with encoding "ISO-8859-1".
+ *
+ * @author Felix Meschberger
+ * @version $Rev:$, $Date:$
+ * @see org.apache.jackrabbit.extension.ExtensionManager
+ * @see org.apache.jackrabbit.extension.NodeTypeSupport
+ */
+
+// The "rep" namespace is expected to be present in the repository.
+// For Jackrabbit based repositories, this is true, for other repositories, we
+// present the namespace declaration here.
+// This declaration is inline with the Jackrabbit internal namespace declaration
+// for the "rep" namespace.
+<rep = 'internal'>
+<nt = 'http://www.jcp.org/jcr/nt/1.0'>
+
+[rep:extension] mixin
+
+- rep:name(string) mandatory copy
+- rep:id(string) mandatory copy
+- rep:class(string) copy
+- rep:classpath(path) multiple copy
+- rep:configurationClass(string) copy
+
++ rep:configuration (nt:base) = nt:unstructured
+	multiple copy
\ No newline at end of file

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/main/resources/org/apache/jackrabbit/extension/type.cnd.bak
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/main/resources/org/apache/jackrabbit/extension/type.cnd.bak?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/main/resources/org/apache/jackrabbit/extension/type.cnd.bak (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/main/resources/org/apache/jackrabbit/extension/type.cnd.bak Wed Dec 21 12:17:51 2005
@@ -0,0 +1,38 @@
+/*
+ * The "type.cnd" file contains the (mixin) node type definition which is
+ * required by the ExtensionManager class.
+ *
+ * NOTE: This file is read through a reader with encoding "ISO-8859-1".
+ *
+ * @author Felix Meschberger
+ * @version $Rev:$, $Date:$
+ * @see org.apache.jackrabbit.extension.ExtensionManager
+ * @see org.apache.jackrabbit.extension.NodeTypeSupport
+ */
+
+// The "rep" namespace is expected to be present in the repository.
+// For Jackrabbit based repositories, this is true, for other repositories, we
+// present the namespace declaration here.
+// This declaration is inline with the Jackrabbit internal namespace declaration
+// for the "rep" namespace.
+<rep = 'internal'>
+<nt = 'http://www.jcp.org/jcr/nt/1.0'>
+
+[rep:extension] mixin
+
+- rep:name(string) mandatory copy
+- rep:id(string) mandatory copy
+- rep:class(string) copy
+- rep:classpath(path) mandatory multiple copy
+- rep:name(string) mandatory copy
+- rep:name(string) mandatory copy
+
+// The "rep:jarContents" is the root node of the subtree into which the archive
+// is unpacked. There is no explicit type requirement for the type of this
+// node, except, that it must be allowed nodes of type "nt:file" and "nt:folder"
+// below. Unpacking the archive in the ExpandingArchiveClassPathEntry class
+// will create the "rep:jarContents" node as an nt:folder node and create files
+// and folders contained in the archive as "nt:file" and "nt:folder" nodes,
+// respectively.
++ rep:jarContents (nt:base) = nt:folder
+	mandatory copy
\ No newline at end of file

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/classes.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/classes.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/classes.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/classes.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,115 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framework - Extension Classes</title>
+    </properties>
+    <body>
+        <section name="Extension Classes">
+            <p>
+                The extension declaration may also contain the (fully
+                qualified) name of a class implementing the extension.
+                Besides finding extension descriptions the Jackrabbit Extension
+                Framework is also able to create instances of extensions
+                and prime them with the extension descriptor, which
+                defined how to instantiate the extension.
+            </p>
+            <p>
+                This page contains information on how class implementing
+                the extensions are loaded how the extensions are then
+                instantiated.
+            </p>
+
+            <subsection name="Loading">
+                <p>
+                    All access to the Jackrabbit Extensions Framework goes
+                    through an instance of the
+                    <code>ExtensionManager</code>
+                    class, which is created using a
+                    <code>Session</code>
+                    and a class loader. While the session is used to
+                    access the repository and also confines access to a
+                    certain workspace, the class loader provided is
+                    actually the basis for loading extension classes.
+                </p>
+                <p>
+                    As has been noted in the
+                    <a href="index.html#Introduction">Introduction</a>
+                    one of the advantages of the Jackrabbit Extension Framework
+                    is its ability to load extension classes from the
+                    repository, an extension may be packaged complete
+                    with the descriptor, optional configuration and the
+                    Java classes and/or archives implementing the
+                    extensions. To be able to load the classes from the
+                    repository, the Jackrabbit Extension Framework uses
+                    instances of the <code>RepositoryClassLoader</code>
+                    provided by the <code>classloader</code> project.
+                </p>
+                <p>
+                    The extension manager creates a separate instance of
+                    the
+                    <code>RepositoryClassLoader</code>
+                    for each extension type accessed. The class path
+                    defined by an extension is added to that class
+                    loader before trying to load the class through that
+                    class loader. The class loader created by the
+                    extension manager is linked into the system class
+                    loader hierarchy by using the application provided
+                    class loader given to the constructor of the
+                    extension manager as its parent class loader.
+                </p>
+                <p>
+                    Please be aware of an issue raising from the fact
+                    that class may be loaded through a class loader
+                    which is a child of the application's class loader:
+                    While extensions have access to all the classes
+                    provided by the repository class loader as well as
+                    the application class loader and all its parents,
+                    the application has no access to the classes loaded
+                    through the repository class loader. This is easily
+                    fixed by having the extensions implement interfaces
+                    which are loaded through the application class
+                    loader and to which the extension instances loaded
+                    through the extension manager may be cast.
+                </p>
+            </subsection>
+
+            <subsection name="Instantiation">
+                <p>
+                    The extension declaration may also contain the
+                    (fully qualified) name of a class implementing the
+                    extension. If so, the Jackrabbit Extension Framework
+                    provides support functionality to load and
+                    instantiate the respective class using either of two
+                    constructors:
+                </p>
+                <ul>
+                    <li>
+                        If the class has a (public) constructor taking
+                        an object of type
+                        <code>
+                            org.apache.jackrabbit.extension.ExtensionDescriptor
+                        </code>
+                        this constructor is used to instanti-ate the
+                        extension instance.
+                    </li>
+                    <li>
+                        Otherwise if the class has a (public) default
+                        constructor this constructor is used to
+                        in-stantiated the extension interface.
+                    </li>
+                    <li>
+                        Otherwise the extension cannot be instantiated.
+                    </li>
+                </ul>
+                <p>
+                    If the extension cannot be instantiated through the
+                    constructor taking the
+                    <code>ExtensionDescriptor</code>
+                    the application is responsible to provide the
+                    relevant information to the extension instance if
+                    required.
+                </p>
+            </subsection>
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/classes.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/configuration.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/configuration.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/configuration.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/configuration.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,162 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framework - Configuration</title>
+    </properties>
+    <body>
+        <section name="Configuration">
+            <p>
+                The Jackrabbit Extension framework supports configuration of
+                the extensions by means of the
+                <a
+                    href="http://jakarta.apache.org/commons/configuration/">
+                    Apache Commons Configuration
+                </a>
+                project. As such, the class specified in the
+                <code>rep:configurationClass</code>
+                property of the extension descriptor must implement the
+                <code>Configuration</code>
+                interface. Generally, it will be an implementation of
+                the
+                <code>RepositoryConfiguration</code>
+                interface, which supports loading and saving of
+                configuration from and to the Jackrabbit repository. The Jackrabbit
+                Extension Framework provides three implementations of
+                the
+                <code>RepositoryConfiguration</code>
+                interface:
+                <code><a href="#ItemConfiguration">ItemConfiguration</a></code>,
+                <code><a href="#PropertiesNodeConfiguration">PropertiesNodeConfiguration</a></code>
+                and
+                <code><a href="#XMLNodeConfiguration">XMLNodeConfiguration</a></code>.
+            </p>
+            <p>
+                The default configuration class used if none is
+                configured in the extension node, is the
+                <code>ItemConfiguration</code>.
+            </p>
+            <p>
+                The configuration object is only created and loaded when
+                the
+                <code>getConfiguration()</code>
+                method of the extension descriptor is first called.
+            </p>
+
+            <subsection name="ItemConfiguration">
+                <p>
+                    The
+                    <code>
+                        <a
+                            href="apidocs/org/apache/jackrabbit/extension/configuration/ItemConfiguration.html">
+                            ItemConfiguration
+                        </a>
+                    </code>
+                    loads a subtree of the repository rooted at the
+                    <code>rep:configuration</code>
+                    child node of the extension node as a
+                    <code>
+                        <a
+                            href="http://jakarta.apache.org/commons/configuration/apidocs/org/apache/commons/configuration/HierarchicalConfiguration.html">
+                            HierarchicalConfiguration</a></code>. Each node
+                    in the subtree becomes a configuration
+                    node and each property becomes an attribute.
+                    Protected nodes and properties (such as
+                    <i>jcr:primaryType</i>) are ignored and neither read nor
+                    written (they cannot be written anyway).
+                </p>
+                <p>
+                    Generally the nodes making up the
+                    <code>ItemConfiguration</code>
+                    will be
+                    <code>nt:unstructured</code>
+                    node thus providing full flexibility for defining
+                    the configuration. When an instance of the
+                    <code>ItemConfiguration</code>
+                    class saves configuration data, this node type is
+                    used for newly created nodes.
+                </p>
+                <p>
+                    <b>Example</b>
+                </p>
+                <source><![CDATA[
+/extensions/sample
+     +-- ... extension descriptor omitted ...
+     +-- rep:configuration
+              +-- handler
+              |        +-- class = "some.Class"
+              |        +-- name = "the name"
+              |        +-- path = [ "/folder1", "/folder2" ]
+              +-- codes
+                       +-- boolean = true
+                       +-- double = 2.5D
+                       +-- long = 10L
+                       +-- string = "a string"
+                       +-- date = 2002-10-11Z19:28]]></source>
+                <p>
+                    The data structure shown above translates into a
+                    configuration data structure with the following
+                    contents. Note the
+                    <i><b>[@</b>name<b>]</b></i>
+                    notation which designates configuration attributes
+                    in contrast to configuration nodes.
+                </p>
+                <source><![CDATA[
+handler[@class] = "some.Class"
+handler[@name] = "the name"
+handler[@path](0) = "/folder1"
+handler[@path](1) = "/folder2"
+handler.codes[@boolean] = true
+handler.codes[@double] = 2.5D
+handler.codes[@long] = 10L
+handler.codes[@string] = "a string"
+handler.codes[@date] = 2002-10-11Z19:28]]></source>
+            </subsection>
+
+            <subsection name="PropertiesNodeConfiguration">
+                <p>
+                    The
+                    <code>
+                        <a
+                            href="apidocs/org/apache/jackrabbit/extension/configuration/PropertiesNodeConfiguration.html">
+                            PropertiesNodeConfiguration
+                        </a>
+                    </code>
+                    extends the
+                    <code>
+                        <a
+                            href="http://jakarta.apache.org/commons/configuration/apidocs/org/apache/commons/configuration/PropertiesConfiguration.html">
+                            PropertiesConfiguration
+                        </a>
+                    </code>
+                    class and supports loading and saving of properties
+                    files from and to the
+                    <code>rep:configuration</code>
+                    property of the extension node.
+                </p>
+            </subsection>
+
+            <subsection name="XMLNodeConfiguration">
+                <p>
+                    The
+                    <code>
+                        <a
+                            href="apidocs/org/apache/jackrabbit/extension/configuration/XMLNodeConfiguration.html">
+                            XMLNodeConfiguration
+                        </a>
+                    </code>
+                    extends the
+                    <code>
+                        <a
+                            href="http://jakarta.apache.org/commons/configuration/apidocs/org/apache/commons/configuration/XMLConfiguration.html">
+                            XMLConfiguration
+                        </a>
+                    </code>
+                    class and supports loading and saving of XML files
+                    from and to the
+                    <code>rep:configuration</code>
+                    property of the extension node.
+                </p>
+            </subsection>
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/configuration.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,36 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framework - Examples</title>
+    </properties>
+    <body>
+        <section name="Examples">
+            <p>Examples provided in this section:</p>
+            <dl>
+                <dt>
+                    <a href="examples/listing.html">
+                        Listing Extensions
+                    </a>
+                </dt>
+                <dd>Shows how to list extensions of a given type.</dd>
+                <dt>
+                    <a href="examples/instantiating.html">
+                        Creating Extension Instances
+                    </a>
+                </dt>
+                <dd>
+                    Shows how to instantiate extensions of a given type.
+                </dd>
+                <dt>
+                    <a href="examples/deployment.html">Deployment</a>
+                </dt>
+                <dd>
+                    Shows a way to deploy an extensions complete with
+                    its descriptor, the classes implementing the
+                    extension and required configuration.
+                </dd>
+            </dl>
+
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/deployment.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/deployment.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/deployment.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/deployment.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framework - Deployment</title>
+    </properties>
+    <body>
+        <section name="Deployment">
+            <p>
+                This sample shows how an extension may be provided in
+                the repository for easy use by the Jackrabbit Extension
+                Framework.
+            </p>
+
+            <source><![CDATA[/extensions/sample            -- node of type nt:folder, rep:extension
+     +-- rep:id = "org.apache.jackrabbit.sample"
+     +-- rep:name = "Sample1"
+     +-- rep:class = "org.apache.jackrabbit.sample.Sample1"
+     +-- rep:classpath = [ /extension/sample/sample.jar ]
+     +-- sample.jar           -- node of type nt:file containing the JAR file
+     +-- rep:configuration    -- node of type nt:file containing the configuration
+              +-- jcr:content
+                       +-- jcr:data -- XML configuration file data]]></source>
+
+            <p>
+                When this extension is loaded, the
+                <code>sample.jar</code>
+                is added to the class loader of the
+                <i>org.apache.jackrabbit.sample</i>
+                extension type and the class
+                <code>org.apache.jackrabbit.sample.Sample1</code>
+                is loaded through that class loader. If the class
+                provides a public constructor taking an instance of
+                <code>ExtensionDescriptor</code>
+                the extension class may access the descriptor's node to
+                get at the configuration stored in the
+                <code>config</code>
+                child node. If the class provides a public setter method
+                for a field of type <code>ExtensionDescriptor</code>, that
+                method is called to set the descriptor.
+            </p>
+            <p>
+                This extension may easily be packaged, distributed and
+                deployed without requiring to hassle around with Jackrabbit
+                runtime configuration.
+            </p>
+
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/deployment.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/instantiating.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/instantiating.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/instantiating.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/instantiating.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framework - Creating Extension Instances</title>
+    </properties>
+    <body>
+        <section name="Creating Extension Instances">
+            <source><![CDATA[// get the session
+Session session = ....;
+
+// get the application class loader
+ClassLoader loader = Sample1.class.getClassLoader();
+
+// get the extension manager
+ExtensionManager mgr = new ExtensionManager(session, loader);
+
+// get iterator for extensions
+Iterator extensions = mgr.findExtensions("org.apache.jackrabbit.sample", null);
+while (extensions.hasNext()) {
+    ExtensionDescriptor desc = (ExtensionDescriptor) extensions.next();
+
+    Object extension = desc.getExtension();
+
+    // handle extension
+}
+
+// dispose of session
+session.logout();]]></source>
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/instantiating.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/listing.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/listing.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/listing.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/listing.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framework - Listing Extensions</title>
+    </properties>
+    <body>
+        <section name="Listing Extensions">
+            <source><![CDATA[// get the session
+Session session = ....;
+
+// get the application class loader
+ClassLoader loader = Sample1.class.getClassLoader();
+
+// get the extension manager
+ExtensionManager mgr = new ExtensionManager(session, loader);
+
+// get iterator for extensions
+Iterator extensions = mgr.findExtensions("org.apache.jackrabbit.sample", null);
+while (extensions.hasNext()) {
+    ExtensionDescriptor desc = (ExtensionDescriptor) extensions.next();
+
+    System.out.println("Extension: ");
+    System.out.println("   Type ID......: " + desc.getId());
+    System.out.println("   Name.........: " + desc.getName());
+
+    System.out.print  ("   Class........: ");
+    if (desc.getClassName() == null) {
+        System.out.println("-");
+    } else {
+        System.out.println(desc.getClassName());
+    }
+
+    System.out.print  ("   Class Path...: ");
+    if (desc.getClassPath() == null) {
+        System.out.println("-");
+    } else {
+        for (int i=0; i < desc.getClassPath().length; i++) {
+            System.out.print((i==0) ? '[' : ',');
+            System.out.print(desc.getClassPath()[i]);
+        }
+        System.out.println("]");
+    }
+}
+
+// dispose of session
+session.logout();]]></source>
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/examples/listing.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/index.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/index.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/index.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/index.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,111 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framwork - Overview</title>
+    </properties>
+    <body>
+        <section name="Introduction">
+            <p>
+                Jackrabbit, the Apache Group's open source implementation
+                of the Content Repository for Java Technology API (JSR
+                170), will be the basis for a series of upcoming
+                products. Some are more integrated with Jackrabbit, like
+                the WebDAV server, some are plain applications of the Jakrabbit,
+                like for example a repository based content management system.
+            </p>
+
+            <p>All of these applications share similar requirements:</p>
+
+            <ul>
+                <li>Extensibility of some sort</li>
+                <li>Configuration requirements</li>
+            </ul>
+
+            <p>
+                To address these common problems and to provide an easy
+                to use framework to jump start on this extensibility
+                issue without requiring tedious configuration steps at
+                different locations, this document proposes the Jackrabbit
+                Extension Framework.
+            </p>
+
+            <p>
+                The core of the Jackrabbit Extension Framework is the
+                <code>
+                    <a
+                        href="apidocs/org/apache/jackrabbit/extension/ExtensionManager.html">
+                        org.apache.jackrabbit.extension.ExtensionManager
+                    </a>
+                </code>
+                which provides the API to load and instantiate
+                extensions for further use. The basic concepts of
+                extensions are as follows:
+            </p>
+
+            <ul>
+                <li>
+                    An extension is part of a group ofextensions sharing
+                    common functionality. Each such group is called an
+                    extension type and has a name. That name, commonly
+                    called the <i>extension type identification</i>, should
+                    be unique within a single application.
+                    There is no additional semantic bound to an
+                    extension type identification. In fact the
+                    uniqueness requirement is not enforced and it is the
+                    sole responsibility of the administrator and/or
+                    extension type implementor to make sure there are no
+                    two extension types with the same identification. A
+                    simple method to handle this issue is to apply the
+                    same naming conventions as proposed by Sun for
+                    <a
+                        href="http://java.sun.com/docs/codeconv/html/CodeConventions.doc8.html#367">
+                        package names
+                    </a>
+                    .
+                </li>
+                <li>
+                    Each extension has a unique name within the realm of
+                    its extension type. Again, this requirement is not
+                    enforced and it is the administrator's or
+                    implementor's responsibility to guarantee this
+                    uniqueness requirement.
+                </li>
+                <li>
+                    An extension may be implemented by some Java code,
+                    which should be loaded into the system for use. That
+                    is, an extension has an associated class and
+                    optionally a class path to indicated where to load
+                    the Java classes from. To simplify deployment of
+                    extensions the classes (or JAR archives) containing
+                    the extension implementation together with optional
+                    required libraries may be stored in the repository.
+                </li>
+                <li>
+                    Often times extensions need to be provided with some
+                    sort of configuration, which of course would also be
+                    stored in the repository.
+                </li>
+            </ul>
+
+            <p>
+                As a consequence of the above noted uniques requirements
+                for extension type identifications and extension names,
+                two instances of the
+                <code>
+                    <a
+                        href="apidocs/org/apache/jackrabbit/extension/ExtensionDescriptor.html">
+                        ExtensionDescriptor
+                    </a>
+                </code>
+                class are considered equal if the have the same type
+                identification and name.
+            </p>
+
+            <p>
+                See
+                <a href="examples/deployment.html">Deployment</a>
+                for a sample extension stored in the repository.
+            </p>
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/index.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/misc.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/misc.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/misc.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/misc.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,40 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framework - Loose Ends</title>
+    </properties>
+    <body>
+        <section name="Dependencies">
+            <p>
+                The Jackrabbit Extension Framework itself has no provision of
+                defining dependencies amongst extensions of a certain
+                type. This has to be implemented in the application of
+                the extension framework.
+            </p>
+            <p>
+                Some examples of how this might be accomplished follow.
+            </p>
+            <subsection name="Priorities">
+                <p>
+                    If the extensions define sort of a operations chain,
+                    a priority may be specified which defines the order
+                    in which the operations are executed. The priority
+                    may be stored in the extension node as an additional
+                    property, which is read by the extension
+                    constructor.
+                </p>
+            </subsection>
+            <subsection name="Dependencies">
+                <p>
+                    If the extensions define services provided which may
+                    have dependencies amongst each other, the respective
+                    dependencies may be stored in an additional property
+                    in the descriptor node, which is read by the
+                    extension constructor. Before actually activating
+                    the services, the dependencies may be handled by the
+                    application to define an activation order.
+                </p>
+            </subsection>
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/misc.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/navigation.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/navigation.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/navigation.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/navigation.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<project>
+ <title>Jackrabbit Extension Framework</title>
+ <body>
+  <menu name="Jackrabbit Extension Framework">
+    <item name="Overview" href="/index.html">
+      <item name="Extension Node Type" href="/nodetype.html" />
+      <item name="Extension Classes" href="/classes.html" />
+      <item name="Configuration" href="/configuration.html" />
+      <item name="Loose Ends" href="/misc.html" />
+    </item>
+    <item name="Examples" href="/examples.html">
+      <item name="Listing Extensions" href="/examples/listing.html" />
+      <item name="Creating Extension Instances" href="/examples/instantiating.html" />
+      <item name="Deployment" href="/examples/deployment.html" />
+    </item>
+  </menu>
+ </body>
+</project>

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/navigation.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/nodetype.xml
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/nodetype.xml?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/nodetype.xml (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/nodetype.xml Wed Dec 21 12:17:51 2005
@@ -0,0 +1,117 @@
+<?xml version="1.0"?>
+<document>
+    <properties>
+        <title>Jackrabbit Extension Framwork - Node Types</title>
+    </properties>
+    <body>
+        <section name="Node Type Definition">
+            <p>
+                A Jackrabbit extension is represented as a node in the
+                repository at an application defined location with mixin
+                node type
+                <code>rep:extension</code>
+                which is defined in compact node type definition format
+                as follows:
+            </p>
+
+            <source><![CDATA[[rep:extension] mixin
+  - rep:name (string) mandatory copy
+  - rep:id (string) mandatory copy
+  - rep:class (string) copy
+  - rep:classpath (path) multiple copy
+  - rep:configurationClass (string) copy
+  + rep:configuration (nt:base) = nt:unstructured multiple copy]]></source>
+
+            <p>
+                The
+                <code>rep:extension</code>
+                type is a mixin node type and as such any node may be
+                designated as the declaring node of an extension. The
+                advantage of this is that the extension declaring node
+                may at the same time be the root node of the extension
+                configuration also read from the repository.
+            </p>
+            <p>
+                The
+                <code>rep:id</code>
+                property contains the name of the extension type
+                provided by this extension. It is recommended that
+                extension type names follow the same pattern of reversed
+                domain name prefixes as is specified for Java packages.
+            </p>
+            <p>
+                The
+                <code>rep:name</code>
+                property contains the name of the extension itself. This
+                name identifies the concrete definitions amongst the set
+                of extensions defined with the same extension type. The
+                name of the extension must be unique amongst all
+                extensions of the same type.
+            </p>
+            <p>
+                The
+                <code>rep:class</code>
+                property contains the fully qualified name of the class
+                implementing this extensions. If this property is not
+                empty, the Jackrabbit Extension Framework is able to provide
+                instantiation support for that class. Refer to the
+                section
+                <a href="classes.html">Extension Classes</a>
+                for explanations of class loading support in the Jackrabbit
+                Extension Framework.
+            </p>
+            <p>
+                The multivalued
+                <code>rep:classpath</code>
+                property contains a list of absolute repository path
+                names denoting the classpath used to load the extension.
+            </p>
+            <p>
+                The
+                <code>rep:configurationClass</code>
+                property contains the fully qualified name of the class,
+                which is used to provide configuration to the extension.
+                The class must implement the
+                <code>
+                    <a
+                        href="http://jakarta.apache.org/commons/configuration/apidocs/org/apache/commons/configuration/Configuration.html">
+                        org.apache.commons.configuration.Configuration
+                    </a>
+                </code>
+                interface. If missing the configuration is loaded
+                through an
+                <code>
+                    <a
+                        href="apidocs/org/apache/jackrabbit/extension/configuration/ItemConfiguration.html">
+                        ItemConfiguration
+                    </a>
+                </code>
+                instance. Refer to the section
+                <a href="configuration.html">Configuration</a>
+                for more information on configuration support of the Jackrabbit
+                Extension Framework.
+            </p>
+            <p>
+                The <code>rep:configuration</code> child node contains the
+                extensions configuration. The
+                <a href="apidocs/org/apache/jackrabbit/extension/ExtensionDescriptor.html#getConfigurationNode()">ExtensionDescriptor.getConfigurationNode</a>
+                method returns this node and the
+                <a href="apidocs/org/apache/jackrabbit/extension/ExtensionDescriptor.html#getConfiguration()">ExtensionDescriptor.getConfiguration</a>
+                method will load the configuration from this node. This node
+                may be of any type. For example it may be a <code>nt:file</code>
+                node whose <code>jcr:content/jcr:data</code> property contains
+                the XML configuration file.
+            </p>
+            <p>
+                The
+                <code>ExtensionManager</code>
+                class loads extensions defined with this node type
+                through its
+                <code>findExtensions</code>
+                method loading the content into instances of the
+                <code>ExtensionDescriptor</code>
+                class for ease of access.
+            </p>
+        </section>
+    </body>
+</document>
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/site/xdoc/nodetype.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFindTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFindTest.java?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFindTest.java (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFindTest.java Wed Dec 21 12:17:51 2005
@@ -0,0 +1,88 @@
+/*
+ * 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.extension;
+
+import java.util.Iterator;
+
+import org.apache.commons.configuration.Configuration;
+
+public class ExtensionFindTest extends ExtensionFrameworkTestBase {
+
+    protected ExtensionManager em;
+
+    protected void setUp() throws Exception {
+        super.setUp();
+        ExtensionManager.checkNodeType(session);
+        fillTestData(session);
+        em = new ExtensionManager(session, getClass().getClassLoader());
+    }
+
+    protected void tearDown() throws Exception {
+        em = null;
+        removeTestData(session);
+        super.tearDown();
+    }
+
+    public void testFindings() throws ExtensionException {
+
+        Iterator ei = em.getExtensions(ID1, ROOT_NODE);
+        while (ei.hasNext()) {
+            ExtensionDescriptor ed = (ExtensionDescriptor) ei.next();
+            System.out.println("Extension " + ed.getId() + "/" + ed.getName() + " (" + ed.getNodePath() +")");
+
+            if (ed.getClassName() != null) {
+                Object ext = ed.getExtension();
+                System.out.println("   Class       : " + ed.getClassName());
+                System.out.println("   ClassLoader : " + ext.getClass().getClassLoader());
+                System.out.println("   Extension   : " + ext);
+            }
+
+            Configuration config = ed.getConfiguration();
+            System.out.println("   Configuration Class : " + config.getClass().getName());
+            System.out.println("   Configuration       : " + config);
+            for (Iterator ki=config.getKeys(); ki.hasNext(); ) {
+                String key = (String) ki.next();
+                Object prop = config.getProperty(key);
+                System.out.println("     " + key + " ==> " + prop);
+            }
+        }
+    }
+
+    public void testFindNonExisting() {
+        try {
+            em.getExtension(ID1, "google", ROOT_NODE);
+        } catch (ExtensionException ee) {
+            assertTrue("Wrong exception " + ee + " thrown",
+                ee.getMessage() != null &&
+                    ee.getMessage().indexOf("not found") > 0);
+        }
+    }
+
+    public void testFindExisting() throws ExtensionException {
+        em.getExtension(ID1, "delivery.core", ROOT_NODE);
+    }
+
+    public void testFindMultipleExisting() {
+        try {
+            em.getExtension(ID1, "delivery.gfx", ROOT_NODE);
+        } catch (ExtensionException ee) {
+            assertTrue("Wrong exception " + ee + " thrown",
+                ee.getMessage() != null &&
+                    ee.getMessage().indexOf("ore than one extension") > 0);
+        }
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFindTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFindTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFrameworkTestBase.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFrameworkTestBase.java?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFrameworkTestBase.java (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFrameworkTestBase.java Wed Dec 21 12:17:51 2005
@@ -0,0 +1,285 @@
+/*
+ * 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.extension;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import javax.jcr.Credentials;
+import javax.jcr.Node;
+import javax.jcr.PathNotFoundException;
+import javax.jcr.RepositoryException;
+import javax.jcr.Session;
+import javax.jcr.SimpleCredentials;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jackrabbit.core.RepositoryImpl;
+import org.apache.jackrabbit.core.config.RepositoryConfig;
+import org.apache.jackrabbit.core.jndi.provider.DummyInitialContextFactory;
+
+/**
+ * The <code>ExtensionFrameworkTestBase</code> TODO
+ *
+ * @author Felix Meschberger
+ * @version $Rev:$, $Date$
+ */
+public class ExtensionFrameworkTestBase extends TestCase {
+
+    /** Logger for test cases */
+    protected static final Log log =
+        LogFactory.getLog("org.apache.jackrabbit.extension.test");
+
+    protected static final String WORKSPACE = "default";
+    protected static final String USER = "admin";
+
+    protected static final String PROVIDER_URL = "ClassLoader";
+    protected static final String REPOSITORY_NAME = "ClassLoaderRepository";
+
+    protected static final String ROOT_NODE = "/services";
+    protected static final String ID1 = "org.apache.jackrabbit.app.services";
+    protected static final String ID2 = "org.apache.jackrabbit.test";
+
+    protected RepositoryImpl repository;
+    protected Session session;
+
+    public ExtensionFrameworkTestBase() {
+        super();
+    }
+
+    public ExtensionFrameworkTestBase(String name) {
+        super(name);
+    }
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        if (!"repositoryStart".equals(getName())) {
+            Context ctx = getInitialContext();
+            repository = (RepositoryImpl) ctx.lookup(REPOSITORY_NAME);
+
+            Credentials creds = new SimpleCredentials(USER, USER.toCharArray());
+            session = repository.login(creds, WORKSPACE);
+        }
+    }
+
+    public void repositoryStart() throws Exception {
+        InputStream config = getClass().getResourceAsStream("/repository.xml");
+        String home = new File("cltest").getAbsolutePath();
+        RepositoryConfig rc = RepositoryConfig.create(config, home);
+        RepositoryImpl repository = RepositoryImpl.create(rc);
+
+        try {
+            Context ctx = getInitialContext();
+            ctx.bind(REPOSITORY_NAME, repository);
+        } catch (NamingException ne) {
+            repository.shutdown();
+            throw ne;
+        }
+    }
+
+    public void repositoryStop() throws Exception {
+        // this is special, logout here and clean repository
+        disconnect();
+        if (repository != null) {
+            repository.shutdown();
+            repository = null;
+        }
+
+        Context ctx = getInitialContext();
+        ctx.unbind(REPOSITORY_NAME);
+    }
+
+    protected void tearDown() throws Exception {
+        disconnect();
+        repository = null;
+        super.tearDown();
+    }
+
+    private Context getInitialContext() throws NamingException {
+        Hashtable env = new Hashtable();
+        env.put(Context.INITIAL_CONTEXT_FACTORY,
+            DummyInitialContextFactory.class.getName());
+        env.put(Context.PROVIDER_URL, PROVIDER_URL);
+
+        return new InitialContext(env);
+    }
+
+    private void disconnect() {
+        if (session != null) {
+            try {
+                removeTestData(session);
+            } catch (RepositoryException re) {
+                // ignore
+            }
+            session.logout();
+            session = null;
+        }
+    }
+
+    //---------- RepositoryLoader ----------------------------------------------
+
+    protected void fillTestData(Session session) throws RepositoryException {
+        try {
+            session.getItem(ROOT_NODE).remove();
+            session.save();
+        } catch (PathNotFoundException ignore) {
+            // ok, if root no extisting
+        }
+
+        // make sure the root is available
+        ensurePath(session, ROOT_NODE);
+
+        fillExtension(session, ROOT_NODE+"/delivery/core", ID1, "delivery.core", null, null, null);
+        fillExtension(session, ROOT_NODE+"/delivery/cache", ID1, "delivery.cache", null, null, null);
+        fillExtension(session, ROOT_NODE+"/delivery/link", ID1, "delivery.link", null, null, null);
+        fillExtension(session, ROOT_NODE+"/delivery/script", ID1, "delivery.script", null, null, null);
+        fillExtension(session, ROOT_NODE+"/delivery/gfx", ID1, "delivery.gfx", null, null, null);
+
+        fillExtension(session, ROOT_NODE+"/development/jsp", ID1, "development.jsp", null, null,
+            "org.apache.jackrabbit.extension.configuration.ItemConfiguration");
+        fillExtension(session, ROOT_NODE+"/development/ecma", ID1, "development.ecma", null, null, null);
+
+        String devCore = ROOT_NODE + "/development/core";
+        fillExtension(session, devCore, ID1, "development.core",
+            "org.apache.jackrabbit.extension.DevCoreTest", devCore+"/classes", null);
+        putClass(session, devCore, "DevCoreTest.class");
+
+        // duplicate extension - ok for iterator, not ok for explicit finding
+        fillExtension(session, ROOT_NODE+"/delivery/gfx2", ID1, "delivery.gfx", null, null, null);
+    }
+
+    protected static void removeTestData(Session session) throws RepositoryException {
+        session.getItem(ROOT_NODE).remove();
+        session.save();
+    }
+
+    private static void fillExtension(Session session, String path, String id,
+            String name, String clazz, String classPath, String configClass)
+            throws RepositoryException {
+
+        // get the extension's node
+        Node extNode = ensurePath(session, path);
+
+        // mark as an extension
+        extNode.addMixin(ExtensionManager.NODE_EXTENSION_TYPE);
+
+        // fill rest
+        trySetProperty(extNode, ExtensionDescriptor.PROP_REP_NAME, name, false);
+        trySetProperty(extNode, ExtensionDescriptor.PROP_REP_ID, id, false);
+        trySetProperty(extNode, ExtensionDescriptor.PROP_REP_CLASS, clazz, false);
+        trySetProperty(extNode, ExtensionDescriptor.PROP_REP_CLASSPATH, classPath, true);
+        trySetProperty(extNode, ExtensionDescriptor.PROP_REP_CONFIGURATION_CLASS, configClass, false);
+
+        // save the node
+        extNode.save();
+    }
+
+    protected static Node ensurePath(Session session, String path) throws RepositoryException {
+        StringTokenizer tokener = new StringTokenizer(path, "/");
+        Node node = session.getRootNode();
+        while (tokener.hasMoreTokens()) {
+            String label = tokener.nextToken();
+
+            if (node.hasNode(label)) {
+                node = node.getNode(label);
+            } else {
+                node = node.addNode(label, "nt:unstructured");
+            }
+        }
+
+        // save all modifications
+        session.save();
+
+        return node;
+    }
+
+    protected static void trySetProperty(Node extNode, String prop, String value,
+            boolean multiple) throws RepositoryException {
+
+        // nothing if no value
+        if (value == null || value.length() == 0) {
+            return;
+        }
+
+        // single value
+        if (!multiple) {
+            extNode.setProperty(prop, value);
+            return;
+        }
+
+        // split multivalue on ","
+        List valueList = new ArrayList();
+        StringTokenizer tokener = new StringTokenizer(value, ",");
+        while (tokener.hasMoreTokens()) {
+            valueList.add(tokener.nextToken());
+        }
+
+        // create value objects
+        ValueFactory vf = extNode.getSession().getValueFactory();
+        Value[] values = new Value[valueList.size()];
+        for (int i=0; i < values.length; i++) {
+            values[i] = vf.createValue((String) valueList.get(i));
+        }
+
+        // set the property
+        extNode.setProperty(prop, values);
+    }
+
+    private void putClass(Session session, String extLoc, String cls) throws RepositoryException {
+        String name = getClass().getName();
+        int lastDot = name.lastIndexOf('.');
+        if (lastDot > 0) name = name.substring(0, lastDot);
+        extLoc += "/classes/" + name.replace('.', '/');
+//        extLoc += "/classes/" +
+//              base.getPackage().getName().replace('.', '/');
+
+        Node pNode = ensurePath(session, extLoc);
+        Node file = pNode.addNode(cls, "nt:file");
+        Node content = file.addNode("jcr:content", "nt:resource");
+        content.setProperty("jcr:mimeType", "application/octet-stream");
+        content.setProperty("jcr:lastModified", Calendar.getInstance());
+
+        InputStream ins = getClass().getResourceAsStream("/"+cls+".bin");
+        if (ins != null) {
+            try {
+                content.setProperty("jcr:data", ins);
+            } finally {
+                try {
+                    ins.close();
+                } catch (IOException ignore) {}
+            }
+        }
+
+        pNode.save();
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFrameworkTestBase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionFrameworkTestBase.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionNodeTypeTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionNodeTypeTest.java?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionNodeTypeTest.java (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionNodeTypeTest.java Wed Dec 21 12:17:51 2005
@@ -0,0 +1,38 @@
+/*
+ * 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.extension;
+
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeTypeManager;
+
+/**
+ * The <code>ExtensionNodeTypeTest</code> TODO
+ *
+ * @author Felix Meschberger
+ * @version $Rev:$, $Date$
+ */
+public class ExtensionNodeTypeTest extends ExtensionFrameworkTestBase {
+
+    public void testNodeType() throws ExtensionException, RepositoryException {
+        NodeTypeManager ntm= session.getWorkspace().getNodeTypeManager();
+
+        // check whether the node type is available
+        ExtensionManager.checkNodeType(session);
+
+        ntm.getNodeType(ExtensionManager.NODE_EXTENSION_TYPE);
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionNodeTypeTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/ExtensionNodeTypeTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/TestAll.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/TestAll.java?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/TestAll.java (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/TestAll.java Wed Dec 21 12:17:51 2005
@@ -0,0 +1,44 @@
+/*
+ * 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.extension;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+import org.apache.jackrabbit.extension.configuration.ItemConfigurationTest;
+
+public class TestAll {
+
+    /**
+     * Returns a <code>Test</code> suite that executes all tests inside this
+     * package.
+     *
+     * @return a <code>Test</code> suite that executes all tests inside this
+     *         package.
+     */
+    public static Test suite() {
+        TestSuite suite = new TestSuite("Extension Tests");
+
+        suite.addTest(new ExtensionFrameworkTestBase("repositoryStart"));
+        suite.addTestSuite(ExtensionNodeTypeTest.class);
+        suite.addTestSuite(ExtensionFindTest.class);
+        suite.addTestSuite(ItemConfigurationTest.class);
+        suite.addTest(new ExtensionFrameworkTestBase("repositoryStop"));
+
+        return suite;
+    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/TestAll.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/TestAll.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/configuration/ItemConfigurationTest.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/configuration/ItemConfigurationTest.java?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/configuration/ItemConfigurationTest.java (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/configuration/ItemConfigurationTest.java Wed Dec 21 12:17:51 2005
@@ -0,0 +1,260 @@
+/*
+ * 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.extension.configuration;
+
+import java.util.Calendar;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.jcr.Item;
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.Value;
+import javax.jcr.ValueFactory;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.commons.configuration.ConfigurationComparator;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.commons.configuration.StrictConfigurationComparator;
+import org.apache.jackrabbit.extension.ExtensionFrameworkTestBase;
+
+
+public class ItemConfigurationTest extends ExtensionFrameworkTestBase {
+
+    private static final String ROOT_PATH = "/config/test";
+    private static final String CFG1 = ROOT_PATH + "/config1";
+    private static final String CFG2 = ROOT_PATH + "/config2";
+//    private static final String CFG3 = ROOT_PATH + "/config3";
+
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        ensurePath(session, ROOT_PATH);
+    }
+
+    protected void tearDown() throws Exception {
+        try {
+            Item item = session.getItem(ROOT_PATH);
+            javax.jcr.Node parent = item.getParent();
+            item.remove();
+            parent.save();
+        } catch (RepositoryException re) {
+            // don't care
+        }
+
+        super.tearDown();
+    }
+
+    public void testCreateAndLoad() throws RepositoryException, ConfigurationException {
+        // this is the manually created
+        Configuration created = createSampleConfig();
+//        dumpConfiguration(created);
+
+        // get the loaded
+        javax.jcr.Node cfgNode = createSampleConfig(CFG1);
+        Configuration loaded = new ItemConfiguration(cfgNode);
+//        dumpConfiguration(loaded);
+
+        // compare configurations
+        ConfigurationComparator comparator = new StrictConfigurationComparator();
+        assertTrue("Configurations differ", comparator.compare(created, loaded));
+    }
+
+    public void testLoadSave() throws RepositoryException, ConfigurationException {
+        // load configuration
+        javax.jcr.Node cfgNode = createSampleConfig(CFG1);
+        ItemConfiguration loaded = new ItemConfiguration(cfgNode);
+//        dumpConfiguration(loaded);
+
+        // store somewhere else
+        Node dest = ensurePath(session, CFG2);
+        loaded.save(dest);
+
+        ItemConfiguration second = new ItemConfiguration(dest);
+//        dumpConfiguration(second);
+
+        // compare configurations
+        ConfigurationComparator comparator = new StrictConfigurationComparator();
+        assertTrue("Configurations differ", comparator.compare(loaded, second));
+    }
+
+    public void testLoadAdditions() throws RepositoryException, ConfigurationException {
+        // load configuration
+        javax.jcr.Node cfgNode = createSampleConfig(CFG1);
+        ItemConfiguration loaded = new ItemConfiguration(cfgNode);
+
+        // add to the configuration
+        loaded.addProperty("added.value[@data]", "Added data");
+        loaded.addProperty("typed.added", "Added to typed");
+        loaded.addProperty("typed[@string]", "Another string");
+
+//        dumpConfiguration("Loaded", loaded);
+
+        // save to the configuration
+        loaded.save();
+
+        // load the same configuration into a new object
+        ItemConfiguration second = new ItemConfiguration(cfgNode);
+//        dumpConfiguration("Second", second);
+
+        // compare configurations
+        ConfigurationComparator comparator = new StrictConfigurationComparator();
+        assertTrue("Configurations differ", comparator.compare(loaded, second));
+    }
+
+    public void testLoadDeletions() throws RepositoryException, ConfigurationException {
+        // load configuration
+        javax.jcr.Node cfgNode = createSampleConfig(CFG1);
+        ItemConfiguration loaded = new ItemConfiguration(cfgNode);
+
+//        dumpConfiguration("Loaded - unmodified", loaded);
+
+        // add to the configuration
+        loaded.clearProperty("typed[@string]");
+        loaded.clearProperty("multivalue[@multi](0)");
+        loaded.clearProperty("sns.same(1)");
+
+//        dumpConfiguration("Loaded - modified", loaded);
+
+        // save to the configuration
+        loaded.save();
+
+        // load the same configuration into a new object
+        ItemConfiguration second = new ItemConfiguration(cfgNode);
+//        dumpConfiguration("Second", second);
+
+        // compare configurations
+        ConfigurationComparator comparator = new StrictConfigurationComparator();
+        assertTrue("Configurations differ", comparator.compare(loaded, second));
+    }
+
+    public void testLoadDeletionsNotSaved() throws RepositoryException, ConfigurationException {
+        // load configuration
+        javax.jcr.Node cfgNode = createSampleConfig(CFG1);
+        ItemConfiguration loaded = new ItemConfiguration(cfgNode);
+
+//        dumpConfiguration("Loaded - unmodified", loaded);
+
+        ItemConfiguration unmodified = new ItemConfiguration(cfgNode);
+//        dumpConfiguration("Unmodified", unmodified);
+
+        // add to the configuration
+        loaded.clearProperty("typed[@string]");
+        loaded.clearProperty("multivalue[@multi](0)");
+        loaded.clearProperty("sns.same(1)");
+
+//        dumpConfiguration("Loaded - modified", loaded);
+
+        // load the same configuration into a new object
+        ItemConfiguration second = new ItemConfiguration(cfgNode);
+//        dumpConfiguration("Second", second);
+
+        // compare configurations
+        ConfigurationComparator comparator = new StrictConfigurationComparator();
+
+        // loaded (modified) and second must be different
+        assertFalse("Configurations are the same", comparator.compare(loaded, second));
+
+        // unmodified and second must bethe same
+        assertTrue("Configurations differ", comparator.compare(unmodified, second));
+    }
+
+    protected HierarchicalConfiguration createSampleConfig() {
+        HierarchicalConfiguration config = new HierarchicalConfiguration();
+
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeInMillis(0);
+
+        config.addProperty("typed[@string]", "value1");
+        config.addProperty("typed[@boolean]", Boolean.TRUE);
+        config.addProperty("typed[@double]", new Double(2.5D));
+        config.addProperty("typed[@long]", new Long(10L));
+        config.addProperty("typed[@date]", cal);
+
+        for (int i=0; i < 5; i++) {
+            config.addProperty("multivalue[@multi]", "multi[" + i+ "]");
+        }
+
+        for (int i=0; i < 3; i++) {
+            config.addProperty("sns.same", "sample" + i);
+        }
+
+        config.addProperty("nodeValue", "This is the node's value");
+
+        return config;
+    }
+
+    protected javax.jcr.Node createSampleConfig(String cfgRoot) throws RepositoryException {
+        javax.jcr.Node cfg = ensurePath(session, cfgRoot + "/rep:configuration");
+
+        Calendar cal = Calendar.getInstance();
+        cal.setTimeInMillis(0);
+
+        // child node with typed properties
+        javax.jcr.Node child = cfg.addNode("typed");
+        child.setProperty("string", "value1");
+        child.setProperty("boolean", true);
+        child.setProperty("double", 2.5D);
+        child.setProperty("long", 10L);
+        child.setProperty("date", cal);
+
+        // child node with multivalue property
+        ValueFactory vf = session.getValueFactory();
+        Value[] multi = new Value[5];
+        for (int i=0; i < multi.length; i++) {
+            multi[i] = vf.createValue("multi[" + i + "]");
+        }
+        child = cfg.addNode("multivalue");
+        child.setProperty("multi", multi);
+
+        // same name sibbling children
+        child = cfg.addNode("sns");
+        child.addNode("same").setProperty("__DEFAULT__", "sample0");
+        child.addNode("same").setProperty("__DEFAULT__", "sample1");
+        child.addNode("same").setProperty("__DEFAULT__", "sample2");
+
+        // __DEFAULT__ value nodes
+        child = cfg.addNode("nodeValue");
+        child.setProperty("__DEFAULT__", "This is the node's value");
+
+        // save everything !!
+        cfg.save();
+
+        return cfg; // .getParent();
+    }
+
+//    private void dumpConfiguration(String title, Configuration config) {
+//        System.out.println();
+//        System.out.println(title);
+//        for (int i=0; i < title.length(); i++) {
+//            System.out.print('-');
+//        }
+//        System.out.println();
+//
+//        Set keys = new TreeSet();
+//        for (Iterator ki=config.getKeys(); ki.hasNext(); ) {
+//            keys.add(ki.next());
+//        }
+//
+//        for (Iterator ki=keys.iterator(); ki.hasNext(); ) {
+//            String key = (String) ki.next();
+//            System.out.println(key + " ==> " + config.getProperty(key));
+//        }
+//    }
+}

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/configuration/ItemConfigurationTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/java/org/apache/jackrabbit/extension/configuration/ItemConfigurationTest.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/resources/DevCoreTest.class.bin
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/test/resources/DevCoreTest.class.bin?rev=358365&view=auto
==============================================================================
Binary file - no diff available.

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/resources/DevCoreTest.class.bin
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/extension-framework/src/test/resources/log4j.properties?rev=358365&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/extension-framework/src/test/resources/log4j.properties (added)
+++ incubator/jackrabbit/trunk/contrib/extension-framework/src/test/resources/log4j.properties Wed Dec 21 12:17:51 2005
@@ -0,0 +1,22 @@
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=INFO, file
+#log4j.rootLogger=DEBUG, stdout, file
+#log4j.rootLogger=ERROR, stdout, file
+
+log4j.logger.org.apache.jackrabbit.extension.test=DEBUG
+
+# 'stdout' is set to be a ConsoleAppender.
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+
+# 'stdout' uses PatternLayout
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{dd.MM.yyyy HH:mm:ss} *%-5p* [%t] %c{1}: %m (%F, line %L)\n
+
+# 'file' is set to be a FileAppender.
+log4j.appender.file=org.apache.log4j.FileAppender
+log4j.appender.file.File=jcr.log
+# log4j.appender.file.Append=false
+
+# 'file' uses PatternLayout.
+log4j.appender.file.layout=org.apache.log4j.PatternLayout
+log4j.appender.file.layout.ConversionPattern=%d{dd.MM.yyyy HH:mm:ss} *%-5p* [%t] %c{1}: %m (%F, line %L)\n

Propchange: incubator/jackrabbit/trunk/contrib/extension-framework/src/test/resources/log4j.properties
------------------------------------------------------------------------------
    svn:eol-style = native