You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@turbine.apache.org by gk...@apache.org on 2021/09/08 13:19:03 UTC

[turbine-fulcrum-factory] 01/49: +) using fulcrum-yaafi-1.0.5 +) getting it to run with maven 1.1

This is an automated email from the ASF dual-hosted git repository.

gk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/turbine-fulcrum-factory.git

commit 4a3b1ba1d93638036c69d1bec06474c38f0fd755
Author: Siegfried Goeschl <sg...@apache.org>
AuthorDate: Thu Oct 25 16:29:42 2007 +0000

    +) using fulcrum-yaafi-1.0.5
    +) getting it to run with maven 1.1
    
    git-svn-id: https://svn.apache.org/repos/asf/turbine/fulcrum/trunk/factory@588276 13f79535-47bb-0310-9956-ffa450edef68
---
 .cvsignore                                         |   6 +
 maven.xml                                          |  26 +
 project.xml                                        |  50 ++
 .../fulcrum/factory/DefaultFactoryService.java     | 544 +++++++++++++++++++++
 src/java/org/apache/fulcrum/factory/Factory.java   | 110 +++++
 .../apache/fulcrum/factory/FactoryException.java   |  43 ++
 .../org/apache/fulcrum/factory/FactoryService.java | 140 ++++++
 .../factory/utils/ObjectInputStreamForContext.java |  70 +++
 src/test/TestComponentConfig.xml                   |  23 +
 src/test/TestRoleConfig.xml                        |  28 ++
 .../apache/fulcrum/factory/FactoryServiceTest.java | 131 +++++
 .../utils/ObjectInputStreamForContextTest.java     |  57 +++
 xdocs/changes.xml                                  |  42 ++
 xdocs/index.xml                                    | 198 ++++++++
 xdocs/navigation.xml                               |  38 ++
 xdocs/tasks.xml                                    |  49 ++
 16 files changed, 1555 insertions(+)

diff --git a/.cvsignore b/.cvsignore
new file mode 100644
index 0000000..e97dd78
--- /dev/null
+++ b/.cvsignore
@@ -0,0 +1,6 @@
+target
+*.log
+.classpath
+.project
+jcoverage.ser
+*.merlin
diff --git a/maven.xml b/maven.xml
new file mode 100644
index 0000000..8c6e127
--- /dev/null
+++ b/maven.xml
@@ -0,0 +1,26 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project default="jar:jar" xmlns:maven="jelly:maven" xmlns:j="jelly:core" xmlns:util="jelly:util">
+
+  <!--preGoal name="java:compile">
+    <attainGoal name="avalon:meta"/>
+  </preGoal-->
+
+</project>
diff --git a/project.xml b/project.xml
new file mode 100644
index 0000000..47be3fe
--- /dev/null
+++ b/project.xml
@@ -0,0 +1,50 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<project>
+  <extend>${basedir}/../project.xml</extend>
+  <id>fulcrum-factory</id>
+  <name>Fulcrum Factory Component</name>
+  <currentVersion>1.0.3</currentVersion>
+  <versions>
+    <version>
+      <id>1.0.3</id>
+      <name>1.0.3</name>
+      <tag>FULCRUM_FACTORY_1_0_3</tag>
+    </version>
+  </versions>
+  <dependencies>
+
+    <!--  Needed only for testing -->
+    <dependency>
+      <groupId>fulcrum</groupId>
+      <artifactId>fulcrum-testcontainer</artifactId>
+      <version>1.0.5</version>
+    </dependency>
+
+    <dependency>
+      <groupId>fulcrum</groupId>
+      <artifactId>fulcrum-yaafi</artifactId>
+      <version>1.0.5</version>
+    </dependency>
+
+  </dependencies>
+
+</project>
+
diff --git a/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java b/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java
new file mode 100644
index 0000000..86472ca
--- /dev/null
+++ b/src/java/org/apache/fulcrum/factory/DefaultFactoryService.java
@@ -0,0 +1,544 @@
+package org.apache.fulcrum.factory;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import org.apache.avalon.framework.activity.Initializable;
+import org.apache.avalon.framework.configuration.Configurable;
+import org.apache.avalon.framework.configuration.Configuration;
+import org.apache.avalon.framework.configuration.ConfigurationException;
+import org.apache.avalon.framework.logger.AbstractLogEnabled;
+import org.apache.fulcrum.factory.utils.ObjectInputStreamForContext;
+
+/**
+ * The Factory Service instantiates objects using specified
+ * class loaders. If none is specified, the default one
+ * will be used.
+ *
+ * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
+ * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
+ * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
+ * @version $Id$
+ *
+ * @avalon.component name="factory" lifestyle="singleton"
+ * @avalon.service type="org.apache.fulcrum.factory.FactoryService"
+ */
+public class DefaultFactoryService
+    extends AbstractLogEnabled
+    implements FactoryService, Configurable, Initializable
+{
+    protected boolean initialized = false;
+    //private boolean disposed = false;
+    /**
+     * The property specifying a set of additional class loaders.
+     */
+    private static final String CLASS_LOADER = "classloader";
+    /**
+     * The property prefix specifying additional object factories.
+     */
+    private static final String OBJECT_FACTORY = "object-factory";
+    /**
+     * The name of the default factory.
+     */
+    protected static final String DEFAULT_FACTORY = "default";
+    /**
+     * Primitive classes for reflection of constructors.
+     */
+    private static HashMap primitiveClasses;
+    {
+        primitiveClasses = new HashMap(8);
+        primitiveClasses.put(Boolean.TYPE.toString(), Boolean.TYPE);
+        primitiveClasses.put(Character.TYPE.toString(), Character.TYPE);
+        primitiveClasses.put(Byte.TYPE.toString(), Byte.TYPE);
+        primitiveClasses.put(Short.TYPE.toString(), Short.TYPE);
+        primitiveClasses.put(Integer.TYPE.toString(), Integer.TYPE);
+        primitiveClasses.put(Long.TYPE.toString(), Long.TYPE);
+        primitiveClasses.put(Float.TYPE.toString(), Float.TYPE);
+        primitiveClasses.put(Double.TYPE.toString(), Double.TYPE);
+    }
+    /**
+     * temporary storage of class names between configure and initialize
+     */
+    private String[] loaderNames;
+    /**
+     * Additional class loaders.
+     */
+    private ArrayList classLoaders = new ArrayList();
+    /**
+     * Customized object factories.
+     */
+    private HashMap objectFactories = new HashMap();
+    /**
+     * Gets the class of a primitive type.
+     *
+     * @param type a primitive type.
+     * @return the corresponding class, or null.
+     */
+    protected static Class getPrimitiveClass(String type)
+    {
+        return (Class) primitiveClasses.get(type);
+    }
+    /**
+     * Constructs a Factory Service.
+     */
+    public DefaultFactoryService()
+    {
+    }
+    /**
+     * Gets an instance of a named class.
+     *
+     * @param className the name of the class.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance(String className) throws FactoryException
+    {
+        if (className == null)
+        {
+            throw new FactoryException("Missing String className");
+        }
+        Factory factory = getFactory(className);
+        if (factory == null)
+        {
+            Class clazz;
+            try
+            {
+                clazz = loadClass(className);
+            }
+            catch (ClassNotFoundException x)
+            {
+                throw new FactoryException("Instantiation failed for class " + className, x);
+            }
+            return getInstance(clazz);
+        }
+        else
+        {
+            return factory.getInstance();
+        }
+    }
+    /**
+     * Gets an instance of a named class using a specified class loader.
+     *
+     * <p>Class loaders are supported only if the isLoaderSupported
+     * method returns true. Otherwise the loader parameter is ignored.
+     *
+     * @param className the name of the class.
+     * @param loader the class loader.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance(String className, ClassLoader loader) throws FactoryException
+    {
+        Factory factory = getFactory(className);
+        if (factory == null)
+        {
+            if (loader != null)
+            {
+                Class clazz;
+                try
+                {
+                    clazz = loadClass(className, loader);
+                }
+                catch (ClassNotFoundException x)
+                {
+                    throw new FactoryException("Instantiation failed for class " + className, x);
+                }
+                return getInstance(clazz);
+            }
+            else
+            {
+                return getInstance(className);
+            }
+        }
+        else
+        {
+            return factory.getInstance(loader);
+        }
+    }
+    /**
+     * Gets an instance of a named class.
+     * Parameters for its constructor are given as an array of objects,
+     * primitive types must be wrapped with a corresponding class.
+     *
+     * @param className the name of the class.
+     * @param params an array containing the parameters of the constructor.
+     * @param signature an array containing the signature of the constructor.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance(String className, Object[] params, String[] signature) throws FactoryException
+    {
+        Factory factory = getFactory(className);
+        if (factory == null)
+        {
+            Class clazz;
+            try
+            {
+                clazz = loadClass(className);
+            }
+            catch (ClassNotFoundException x)
+            {
+                throw new FactoryException("Instantiation failed for class " + className, x);
+            }
+            return getInstance(clazz, params, signature);
+        }
+        else
+        {
+            return factory.getInstance(params, signature);
+        }
+    }
+    /**
+     * Gets an instance of a named class using a specified class loader.
+     * Parameters for its constructor are given as an array of objects,
+     * primitive types must be wrapped with a corresponding class.
+     *
+     * <p>Class loaders are supported only if the isLoaderSupported
+     * method returns true. Otherwise the loader parameter is ignored.
+     *
+     * @param className the name of the class.
+     * @param loader the class loader.
+     * @param params an array containing the parameters of the constructor.
+     * @param signature an array containing the signature of the constructor.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance(String className, ClassLoader loader, Object[] params, String[] signature)
+        throws FactoryException
+    {
+        Factory factory = getFactory(className);
+        if (factory == null)
+        {
+            if (loader != null)
+            {
+                Class clazz;
+                try
+                {
+                    clazz = loadClass(className, loader);
+                }
+                catch (ClassNotFoundException x)
+                {
+                    throw new FactoryException("Instantiation failed for class " + className, x);
+                }
+                return getInstance(clazz, params, signature);
+            }
+            else
+            {
+                return getInstance(className, params, signature);
+            }
+        }
+        else
+        {
+            return factory.getInstance(loader, params, signature);
+        }
+    }
+    /**
+     * Tests if specified class loaders are supported for a named class.
+     *
+     * @param className the name of the class.
+     * @return true if class loaders are supported, false otherwise.
+     * @throws FactoryException if test fails.
+     */
+    public boolean isLoaderSupported(String className) throws FactoryException
+    {
+        Factory factory = getFactory(className);
+        return factory != null ? factory.isLoaderSupported() : true;
+    }
+    /**
+     * Gets an instance of a specified class.
+     *
+     * @param clazz the class.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance(Class clazz) throws FactoryException
+    {
+        try
+        {
+            return clazz.newInstance();
+        }
+        catch (Exception x)
+        {
+            throw new FactoryException("Instantiation failed for " + clazz.getName(), x);
+        }
+    }
+    /**
+     * Gets an instance of a specified class.
+     * Parameters for its constructor are given as an array of objects,
+     * primitive types must be wrapped with a corresponding class.
+     *
+     * @param clazz the class.
+     * @param params an array containing the parameters of the constructor.
+     * @param signature an array containing the signature of the constructor.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    protected Object getInstance(Class clazz, Object params[], String signature[]) throws FactoryException
+    {
+        /* Try to construct. */
+        try
+        {
+            Class[] sign = getSignature(clazz, params, signature);
+            return clazz.getConstructor(sign).newInstance(params);
+        }
+        catch (Exception x)
+        {
+            throw new FactoryException("Instantiation failed for " + clazz.getName(), x);
+        }
+    }
+    /**
+     * Gets the signature classes for parameters of a method of a class.
+     *
+     * @param clazz the class.
+     * @param params an array containing the parameters of the method.
+     * @param signature an array containing the signature of the method.
+     * @return an array of signature classes. Note that in some cases
+     * objects in the parameter array can be switched to the context
+     * of a different class loader.
+     * @throws ClassNotFoundException if any of the classes is not found.
+     */
+    public Class[] getSignature(Class clazz, Object params[], String signature[]) throws ClassNotFoundException
+    {
+        if (signature != null)
+        {
+            /* We have parameters. */
+            ClassLoader tempLoader;
+            ClassLoader loader = clazz.getClassLoader();
+            Class[] sign = new Class[signature.length];
+            for (int i = 0; i < signature.length; i++)
+            {
+                /* Check primitive types. */
+                sign[i] = getPrimitiveClass(signature[i]);
+                if (sign[i] == null)
+                {
+                    /* Not a primitive one, continue building. */
+                    if (loader != null)
+                    {
+                        /* Use the class loader of the target object. */
+                        sign[i] = loader.loadClass(signature[i]);
+                        tempLoader = sign[i].getClassLoader();
+                        if ((params[i] != null)
+                            && (tempLoader != null)
+                            && !tempLoader.equals(params[i].getClass().getClassLoader()))
+                        {
+                            /*
+                             * The class uses a different class loader,
+                             * switch the parameter.
+                             */
+                            params[i] = switchObjectContext(params[i], loader);
+                        }
+                    }
+                    else
+                    {
+                        /* Use the default class loader. */
+                        sign[i] = loadClass(signature[i]);
+                    }
+                }
+            }
+            return sign;
+        }
+        else
+        {
+            return null;
+        }
+    }
+    /**
+     * Switches an object into the context of a different class loader.
+     *
+     * @param object an object to switch.
+     * @param loader the loader of the new context.
+     */
+    protected Object switchObjectContext(Object object, ClassLoader loader)
+    {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        try
+        {
+            ObjectOutputStream out = new ObjectOutputStream(bout);
+            out.writeObject(object);
+            out.flush();
+        }
+        catch (Exception x)
+        {
+            return object;
+        }
+        try
+        {
+            ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+            ObjectInputStreamForContext in = new ObjectInputStreamForContext(bin, loader);
+            return in.readObject();
+        }
+        catch (Exception x)
+        {
+            return object;
+        }
+    }
+    /**
+     * Loads the named class using the default class loader.
+     *
+     * @param className the name of the class to load.
+     * @return the loaded class.
+     * @throws ClassNotFoundException if the class was not found.
+     */
+    protected Class loadClass(String className) throws ClassNotFoundException
+    {
+        ClassLoader loader = this.getClass().getClassLoader();
+        try
+        {
+            return loader != null ? loader.loadClass(className) : Class.forName(className);
+        }
+        catch (ClassNotFoundException x)
+        {
+            /* Go through additional loaders. */
+            for (Iterator i = classLoaders.iterator(); i.hasNext();)
+            {
+                try
+                {
+                    return ((ClassLoader) i.next()).loadClass(className);
+                }
+                catch (ClassNotFoundException xx)
+                {
+                }
+            }
+            /* Give up. */
+            throw x;
+        }
+    }
+    /**
+     * Loads the named class using a specified class loader.
+     *
+     * @param className the name of the class to load.
+     * @param loader the loader to use.
+     * @return the loaded class.
+     * @throws ClassNotFoundException if the class was not found.
+     */
+    protected Class loadClass(String className, ClassLoader loader) throws ClassNotFoundException
+    {
+        return loader != null ? loader.loadClass(className) : loadClass(className);
+    }
+    /**
+     * Gets a customized factory for a named class. If no class-specific
+     * factory is specified but a default factory is, will use the default
+     * factory.
+     *
+     * @param className the name of the class to load.
+     * @return the factory, or null if not specified and no default.
+     * @throws FactoryException if instantiation of the factory fails.
+     */
+    protected Factory getFactory(String className) throws FactoryException
+    {
+        HashMap factories = objectFactories;
+        Object factory = factories.get(className);
+        if (factory == null)
+        {
+            //No named factory for this; try the default, if one
+            //exists.
+            factory = factories.get(DEFAULT_FACTORY);
+        }
+        if (factory != null)
+        {
+            if (factory instanceof String)
+            {
+                /* Not yet instantiated... */
+                try
+                {
+                    factory = (Factory) getInstance((String) factory);
+                    ((Factory) factory).init(className);
+                }
+                catch (FactoryException x)
+                {
+                    throw x;
+                }
+                catch (ClassCastException x)
+                {
+                    throw new FactoryException("Incorrect factory " + (String) factory + " for class " + className, x);
+                }
+                factories = (HashMap) factories.clone();
+                factories.put(className, factory);
+                objectFactories = factories;
+            }
+            return (Factory) factory;
+        }
+        else
+        {
+            return null;
+        }
+    }
+    // ---------------- Avalon Lifecycle Methods ---------------------
+    /**
+     * Avalon component lifecycle method
+     */
+    public void configure(Configuration conf) throws ConfigurationException
+    {
+        final Configuration[] loaders = conf.getChildren(CLASS_LOADER);
+        if (loaders != null)
+        {
+            loaderNames = new String[loaders.length];
+            for (int i = 0; i < loaders.length; i++)
+            {
+                loaderNames[i] = loaders[i].getValue();
+            }
+        }
+        final Configuration factories = conf.getChild(OBJECT_FACTORY, false);
+        if (factories != null)
+        {
+            Configuration[] nameVal = factories.getChildren();
+            for (int i = 0; i < nameVal.length; i++)
+            {
+                String key = nameVal[i].getName();
+                String factory = nameVal[i].getValue();
+                // Store the factory to the table as a string and
+                // instantiate it by using the service when needed.
+                objectFactories.put(key, factory);
+            }
+        }
+    }
+    /**
+     * Avalon component lifecycle method
+     * Initializes the service by loading default class loaders
+     * and customized object factories.
+     *
+     * @throws InitializationException if initialization fails.
+     */
+    public void initialize() throws Exception
+    {
+        if (loaderNames != null)
+        {
+            for (int i = 0; i < loaderNames.length; i++)
+            {
+                try
+                {
+                    classLoaders.add(loadClass(loaderNames[i]).newInstance());
+                }
+                catch (Exception x)
+                {
+                    throw new Exception(
+                        "No such class loader '" + loaderNames[i] + "' for DefaultFactoryService",
+                        x);
+                }
+            }
+            loaderNames = null;
+        }
+    }
+}
diff --git a/src/java/org/apache/fulcrum/factory/Factory.java b/src/java/org/apache/fulcrum/factory/Factory.java
new file mode 100644
index 0000000..841d30c
--- /dev/null
+++ b/src/java/org/apache/fulcrum/factory/Factory.java
@@ -0,0 +1,110 @@
+package org.apache.fulcrum.factory;
+
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+
+/**
+ * Factory is an interface for object factories. Object factories
+ * can be registered with the Factory Service to support customized
+ * functionality during instantiation of specific classes that
+ * the service itself cannot provide. Examples include
+ * instantiation of XML parsers and secure sockets requiring
+ * provider specific initializations before instantiation.
+ *
+ * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
+ * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
+ * @version $Id$
+ */
+public interface Factory
+{
+    /**
+     * Initializes the factory. This method is called by
+     * the Factory Service before the factory is used.
+     *
+     * @param className the name of the production class
+     * @throws FactoryException if initialization fails.
+     */
+    public void init(String className)
+        throws FactoryException;
+
+    /**
+     * Gets an instance of a class.
+     *
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance()
+        throws FactoryException;
+
+    /**
+     * Gets an instance of a class using a specified class loader.
+     *
+     * <p>Class loaders are supported only if the isLoaderSupported
+     * method returns true. Otherwise the loader parameter is ignored.
+     *
+     * @param loader the class loader.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance(ClassLoader loader)
+        throws FactoryException;
+
+    /**
+     * Gets an instance of a named class.
+     * Parameters for its constructor are given as an array of objects,
+     * primitive types must be wrapped with a corresponding class.
+     *
+     * @param params an array containing the parameters of the constructor.
+     * @param signature an array containing the signature of the constructor.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance(Object[] params,
+                              String[] signature)
+        throws FactoryException;
+
+    /**
+     * Gets an instance of a named class using a specified class loader.
+     * Parameters for its constructor are given as an array of objects,
+     * primitive types must be wrapped with a corresponding class.
+     *
+     * <p>Class loaders are supported only if the isLoaderSupported
+     * method returns true. Otherwise the loader parameter is ignored.
+     *
+     * @param loader the class loader.
+     * @param params an array containing the parameters of the constructor.
+     * @param signature an array containing the signature of the constructor.
+     * @return the instance.
+     * @throws FactoryException if instantiation fails.
+     */
+    public Object getInstance(ClassLoader loader,
+                              Object[] params,
+                              String[] signature)
+        throws FactoryException;
+
+    /**
+     * Tests if this object factory supports specified class loaders.
+     *
+     * @return true if class loaders are supported, false otherwise.
+     */
+    public boolean isLoaderSupported();
+}
diff --git a/src/java/org/apache/fulcrum/factory/FactoryException.java b/src/java/org/apache/fulcrum/factory/FactoryException.java
new file mode 100644
index 0000000..63c1ee0
--- /dev/null
+++ b/src/java/org/apache/fulcrum/factory/FactoryException.java
@@ -0,0 +1,43 @@
+package org.apache.fulcrum.factory;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/**
+ * Exception thrown when there is a problem with the FactoryService
+ *
+ * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
+ * @version $Id$
+ */
+public class FactoryException extends Exception
+{
+    /**
+     * Serial number
+     */
+    private static final long serialVersionUID = 8954422192583295720L;
+
+    public FactoryException(String msg)
+    {
+        super(msg);
+    }
+    public FactoryException(String msg, Exception ex)
+    {
+        super(msg, ex);
+    }
+}
diff --git a/src/java/org/apache/fulcrum/factory/FactoryService.java b/src/java/org/apache/fulcrum/factory/FactoryService.java
new file mode 100644
index 0000000..e4e2f5f
--- /dev/null
+++ b/src/java/org/apache/fulcrum/factory/FactoryService.java
@@ -0,0 +1,140 @@
+package org.apache.fulcrum.factory;
+
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+
+/**
+ * The Factory Service instantiates objects using either default
+ * class loaders or a specified one. Whether specified class
+ * loaders are supported for a class depends on implementation
+ * and can be tested with the isLoaderSupported method.
+ *
+ * @author <a href="mailto:epugh@upstate.com">Eric Pugh</a>
+ * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
+ * @version $Id$
+ */
+public interface FactoryService
+{
+    /**
+     * The key under which this component is known by an avalon container.
+     */
+    String ROLE = FactoryService.class.getName();
+
+
+	/**
+	* Gets an instance of a class.
+	*
+	* @param clazz the name of the class.
+	* @return the instance.
+	* @throws ServiceException if instantiation fails.
+	*/
+   public Object getInstance(Class clazz)
+	   throws FactoryException;
+
+    /**
+     * Gets an instance of a named class.
+     *
+     * @param className the name of the class.
+     * @return the instance.
+     * @throws ServiceException if instantiation fails.
+     */
+    public Object getInstance(String className)
+        throws FactoryException;
+
+    /**
+     * Gets an instance of a named class using a specified class loader.
+     *
+     * <p>Class loaders are supported only if the isLoaderSupported
+     * method returns true. Otherwise the loader parameter is ignored.
+     *
+     * @param className the name of the class.
+     * @param loader the class loader.
+     * @return the instance.
+     * @throws ServiceException if instantiation fails.
+     */
+    public Object getInstance(String className,
+                              ClassLoader loader)
+        throws FactoryException;
+
+    /**
+     * Gets an instance of a named class.
+     * Parameters for its constructor are given as an array of objects,
+     * primitive types must be wrapped with a corresponding class.
+     *
+     * @param className the name of the class.
+     * @param params an array containing the parameters of the constructor.
+     * @param signature an array containing the signature of the constructor.
+     * @return the instance.
+     * @throws ServiceException if instantiation fails.
+     */
+    public Object getInstance(String className,
+                              Object[] params,
+                              String[] signature)
+        throws FactoryException;
+
+    /**
+     * Gets an instance of a named class using a specified class loader.
+     * Parameters for its constructor are given as an array of objects,
+     * primitive types must be wrapped with a corresponding class.
+     *
+     * <p>Class loaders are supported only if the isLoaderSupported
+     * method returns true. Otherwise the loader parameter is ignored.
+     *
+     * @param className the name of the class.
+     * @param loader the class loader.
+     * @param params an array containing the parameters of the constructor.
+     * @param signature an array containing the signature of the constructor.
+     * @return the instance.
+     * @throws ServiceException if instantiation fails.
+     */
+    public Object getInstance(String className,
+                              ClassLoader loader,
+                              Object[] params,
+                              String[] signature)
+        throws FactoryException;
+
+    /**
+     * Tests if specified class loaders are supported for a named class.
+     *
+     * @param className the name of the class.
+     * @return true if class loaders are supported, false otherwise.
+     * @throws ServiceException if test fails.
+     */
+    public boolean isLoaderSupported(String className)
+        throws FactoryException;
+
+    /**
+     * Gets the signature classes for parameters of a method of a class.
+     *
+     * @param clazz the class.
+     * @param params an array containing the parameters of the method.
+     * @param signature an array containing the signature of the method.
+     * @return an array of signature classes. Note that in some cases
+     * objects in the parameter array can be switched to the context
+     * of a different class loader.
+     * @throws ClassNotFoundException if any of the classes is not found.
+     */
+    Class[] getSignature(Class clazz,
+            Object params[],
+            String signature[])
+            throws ClassNotFoundException;
+}
diff --git a/src/java/org/apache/fulcrum/factory/utils/ObjectInputStreamForContext.java b/src/java/org/apache/fulcrum/factory/utils/ObjectInputStreamForContext.java
new file mode 100644
index 0000000..a0fb934
--- /dev/null
+++ b/src/java/org/apache/fulcrum/factory/utils/ObjectInputStreamForContext.java
@@ -0,0 +1,70 @@
+package org.apache.fulcrum.factory.utils;
+
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectStreamClass;
+import java.io.IOException;
+
+/**
+ * A deserialization stream for a specific class loader context.
+ *
+ * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
+ * @version $Id$
+ */
+public class ObjectInputStreamForContext extends ObjectInputStream
+{
+    /**
+     * The class loader of the context.
+     */
+    private ClassLoader classLoader;
+
+    // this is to make the proxy happy.
+    public ObjectInputStreamForContext()
+        throws IOException
+    {
+    }
+
+    /**
+     * Contructs a new object stream for a context.
+     *
+     * @param in the serialized input stream.
+     * @param loader the class loader of the context.
+     * @throws IOException on errors.
+     */
+    public  ObjectInputStreamForContext(InputStream in,
+                                        ClassLoader loader)
+                                        throws IOException
+    {
+        super(in);
+        classLoader = loader;
+    }
+
+    protected Class resolveClass(ObjectStreamClass v)
+                                 throws IOException,
+                                 ClassNotFoundException
+    {
+        return classLoader == null ?
+            super.resolveClass(v) : classLoader.loadClass(v.getName());
+    }
+}
diff --git a/src/test/TestComponentConfig.xml b/src/test/TestComponentConfig.xml
new file mode 100644
index 0000000..d027290
--- /dev/null
+++ b/src/test/TestComponentConfig.xml
@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<componentConfig>
+
+    <factory/>
+</componentConfig>
diff --git a/src/test/TestRoleConfig.xml b/src/test/TestRoleConfig.xml
new file mode 100644
index 0000000..8918105
--- /dev/null
+++ b/src/test/TestRoleConfig.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<!-- This configuration file for Avalon components is used for testing the TestComponent -->
+<role-list>
+    <role
+        name="org.apache.fulcrum.factory.FactoryService"
+        shorthand="factory"
+        default-class="org.apache.fulcrum.factory.DefaultFactoryService"/>
+
+
+</role-list>
diff --git a/src/test/org/apache/fulcrum/factory/FactoryServiceTest.java b/src/test/org/apache/fulcrum/factory/FactoryServiceTest.java
new file mode 100644
index 0000000..eb97a08
--- /dev/null
+++ b/src/test/org/apache/fulcrum/factory/FactoryServiceTest.java
@@ -0,0 +1,131 @@
+package org.apache.fulcrum.factory;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+
+import java.util.ArrayList;
+import org.apache.fulcrum.testcontainer.BaseUnitTest;
+
+/**
+ * @author Eric Pugh
+ * @author <a href="mailto:mcconnell@apache.org">Stephen McConnell</a>
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+public class FactoryServiceTest extends BaseUnitTest
+{
+    private FactoryService factoryService = null;
+    /**
+     * Defines the testcase name for JUnit.
+     *
+     * @param name the testcase's name.
+     */
+    public FactoryServiceTest(String name)
+    {
+        super(name);
+    }
+
+    public void setUp() throws Exception
+    {
+        super.setUp();
+        factoryService = (FactoryService) this.resolve( FactoryService.class.getName() );
+
+    }
+    /*
+     * Class to test for Object getInstance(String)
+     */
+    public void testGetInstanceString() throws Exception
+    {
+        Object object = factoryService.getInstance("java.lang.StringBuffer");
+        assertTrue(object instanceof StringBuffer);
+    }
+    /*
+     * Class to test for Object getInstance(String, ClassLoader)
+     */
+    public void testGetInstanceStringClassLoader() throws Exception
+    {
+        Object object = factoryService.getInstance("java.lang.StringBuffer", StringBuffer.class.getClassLoader());
+        assertTrue(object instanceof StringBuffer);
+    }
+    /*
+     * Class to test for Object getInstance(String, Object[], String[])
+     */
+    public void testGetInstanceStringObjectArrayStringArray() throws Exception
+    {
+        Object params[] = new Object[1];
+        String sourceValue = "testing";
+        params[0] = sourceValue;
+        String signature[] = new String[1];
+        signature[0] = "java.lang.String";
+        Object object = factoryService.getInstance("java.lang.StringBuffer", params, signature);
+        assertTrue(object instanceof StringBuffer);
+        assertEquals(sourceValue, object.toString());
+
+    }
+    /*
+     * Class to test for Object getInstance(String, ClassLoader, Object[], String[])
+     */
+    public void testGetInstanceStringClassLoaderObjectArrayStringArray() throws Exception
+    {
+        Object params[] = new Object[1];
+        String sourceValu = "testing";
+        params[0] = sourceValu;
+        String signature[] = new String[1];
+        signature[0] = "java.lang.String";
+        Object object =
+            factoryService.getInstance(
+                "java.lang.StringBuffer",
+                StringBuffer.class.getClassLoader(),
+                params,
+                signature);
+        assertTrue(object instanceof StringBuffer);
+        assertEquals(sourceValu, object.toString());
+
+    }
+    /**
+     * @todo Need to run a test where the loader is NOT supported.
+     * @throws Exception
+     */
+    public void testIsLoaderSupported() throws Exception
+    {
+        assertTrue(factoryService.isLoaderSupported("java.lang.String"));
+
+    }
+    public void testGetSignature() throws Exception
+    {
+        Object params[] = new Object[1];
+        String sourceValu = "testing";
+        params[0] = sourceValu;
+        String signature[] = new String[1];
+        signature[0] = "java.lang.String";
+        Class[] results = factoryService.getSignature(StringBuffer.class, params, signature);
+        assertEquals(1, results.length);
+        assertTrue(results[0].equals(String.class));
+
+        Integer sourceValueInteger = new Integer(10);
+        params[0] = sourceValueInteger;
+        signature[0] = "java.lang.Integer";
+        results = factoryService.getSignature(ArrayList.class, params, signature);
+        assertEquals(1, results.length);
+        assertTrue("Result:" + results[0].getName(),results[0].equals(Integer.class));
+
+    }
+}
diff --git a/src/test/org/apache/fulcrum/factory/utils/ObjectInputStreamForContextTest.java b/src/test/org/apache/fulcrum/factory/utils/ObjectInputStreamForContextTest.java
new file mode 100644
index 0000000..f00fa7e
--- /dev/null
+++ b/src/test/org/apache/fulcrum/factory/utils/ObjectInputStreamForContextTest.java
@@ -0,0 +1,57 @@
+package org.apache.fulcrum.factory.utils;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectOutputStream;
+import junit.framework.TestCase;
+
+/**
+ * @author Eric Pugh
+ *
+ * To change the template for this generated type comment go to
+ * Window>Preferences>Java>Code Generation>Code and Comments
+ */
+
+public class ObjectInputStreamForContextTest extends TestCase
+{
+    public static void main(String[] args)
+    {
+        junit.textui.TestRunner.run(ObjectInputStreamForContextTest.class);
+    }
+    /*
+     * Class to test for void ObjectInputStreamForContext(InputStream, ClassLoader)
+     */
+    public void testObjectInputStreamForContextInputStreamClassLoader() throws Exception
+    {
+        Object object = new String("I am testing");
+        Object object2 = null;
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        ObjectOutputStream out = new ObjectOutputStream(bout);
+        out.writeObject(object);
+        out.flush();
+        ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
+        ObjectInputStreamForContext in = new ObjectInputStreamForContext(bin, String.class.getClassLoader());
+        object2 = in.readObject();
+        assertEquals(object.toString(), object2.toString());
+        assertEquals(object, object2);
+    }
+}
diff --git a/xdocs/changes.xml b/xdocs/changes.xml
new file mode 100644
index 0000000..bcc5886
--- /dev/null
+++ b/xdocs/changes.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<document>
+  <properties>
+    <title>Fulcrum Factory</title>
+    <author email="epugh@opensourceconnections.com">Eric Pugh</author>
+  </properties>
+
+  <body>
+    <release version="1.0.3" date="2004-11-24">
+      <action dev="epugh" type="update" due-to="Kostyantyn Shchekotykhin">
+        Merge api and impl jars into one project.
+      </action>
+      <action dev="epugh" type="update">
+      	Clean up dependencies.  Use TestContainer.
+      </action>
+    </release>
+	<release version="1.0.2" date="">
+      <action dev="epugh" type="update">
+      	Update to use Merlin 3.3.0
+      </action>
+    </release>
+  </body>
+</document>
+
diff --git a/xdocs/index.xml b/xdocs/index.xml
new file mode 100644
index 0000000..74e7d09
--- /dev/null
+++ b/xdocs/index.xml
@@ -0,0 +1,198 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<document>
+
+  <properties>
+    <title>Factory Component</title>
+    <author email="epugh@upstate.com">Eric PUgh</author>
+  </properties>
+
+  <body>
+
+  <section name="Overview">
+<p>
+The Factory Service instantiates objects from the given class name
+using either the given class loader or an applicable one found from the class
+loader repository. If neither one is specified, the default class loader
+will be used.
+</p>
+
+<p>
+The service provides the following benefits compared to Class.forName():
+</p>
+<ul>
+<li>support for parameters in constructors,</li>
+<li>internal class loader repository, which can be specified in resources,</li>
+<li>optional class specific factories, which can be used for customized instantiation, and</li>
+<li>integration with the Pool Service supporting recycling of instances created by the service.</li>
+</ul>
+  </section>
+
+<section name="Configuration">
+
+    <p>
+      First, here is the role configuration.
+    </p>
+
+<source>
+<![CDATA[
+   <role
+        name="org.apache.fulcrum.factory.FactoryService"
+        shorthand="factory"
+        default-class="org.apache.fulcrum.factory.DefaultFactoryService"/>
+]]>
+</source>
+
+  <p>
+    There is configuration values for classloaders, still need to add.
+  </p>
+<source>
+
+<![CDATA[
+    <factory/>
+]]>
+</source>
+
+  </section>
+
+  <section name="Usage">
+
+<p>
+In Turbine, the Factory Service is currently only used internally by the Pool Service.
+Applications can also use the service instead of Class.forName() and for unifying
+initialization, configuration and access to vendor specific object factories.
+The following is a simplified example of a customized DOM parser factory:
+</p>
+
+<source><![CDATA[
+package org.foo.xml;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
+import org.apache.fulcrum.ServiceException;
+import org.apache.fulcrum.factory.Factory;
+
+/**
+ * A factory for instantiating DOM parsers.
+ */
+public class DomBuilderFactory implements Factory
+{
+    /**
+     * The implementation of the factory.
+     */
+    private DocumentBuilderFactory factory;
+
+    /**
+     * Initializes the factory.
+     */
+    public void init(String className)
+        throws ServiceException
+    {
+        factory = DocumentBuilderFactory.newInstance();
+    }
+
+    /**
+     * Gets a DocumentBuilder instance.
+     */
+    public Object getInstance()
+        throws ServiceException
+    {
+        try
+        {
+            return factory.newDocumentBuilder();
+        }
+        catch (ParserConfigurationException x)
+        {
+            throw new TurbineException(x);
+        }
+    }
+
+    /**
+     * Gets a DocumentBuilder instance.
+     * The given loader is ignored.
+     */
+    public Object getInstance(ClassLoader loader)
+        throws ServiceException
+    {
+        return getInstance();
+    }
+
+    /**
+     * Gets a DocumentBuilder instance.
+     * Constructor parameters are ignored.
+     */
+    public Object getInstance(Object[] params,
+                              String[] signature)
+        throws ServiceException
+    {
+        return getInstance();
+    }
+
+    /**
+     * Gets a DocumentBuilder instance.
+     * The given loader and constructor parameters are ignored.
+     */
+    public Object getInstance(ClassLoader loader,
+                              Object[] params,
+                              String[] signature)
+        throws ServiceException
+    {
+        return getInstance();
+    }
+
+    /**
+     * Returns false as given class loaders are not supported.
+     */
+    public boolean isLoaderSupported()
+    {
+        return false;
+    }
+}
+]]></source>
+
+<p>
+The customized DOM parser factory must be specified in Turbine Resources before it can be used:
+</p>
+
+<source><![CDATA[
+services.FactoryService.factory.javax.xml.parsers.DocumentBuilder=org.foo.xml.DomBuilderFactory
+]]></source>
+
+<p>
+A DOM parser can now be instantiated with the following code fragment:
+</p>
+
+<source><![CDATA[
+// Access the service singleton.
+FactoryService service = (FactoryService)
+    TurbineServices.getInstance().getService(FactoryService.SERVICE_NAME);
+
+// Create a new DOM parser.
+DocumentBuilder parser =
+    service.getInstance("javax.xml.parsers.DocumentBuilder");
+]]></source>
+
+  </section>
+
+</body>
+</document>
diff --git a/xdocs/navigation.xml b/xdocs/navigation.xml
new file mode 100644
index 0000000..0fead1d
--- /dev/null
+++ b/xdocs/navigation.xml
@@ -0,0 +1,38 @@
+<?xml version="1.0" encoding="ISO-8859-1"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+
+<!DOCTYPE project [
+<!ENTITY site-nav SYSTEM "../../incl_site_nav.xml">
+]>
+
+<project
+  name="Fulcrum Factory"
+  href="http://turbine.apache.org/fulcrum/fulcrum-factory/">
+
+  <body>
+
+&site-nav;
+
+    <menu name="Overview">
+      <item name="Main"                 href="/index.html"/>
+      <item name="Tasks"                href="/tasks.html"/>
+    </menu>
+  </body>
+</project>
diff --git a/xdocs/tasks.xml b/xdocs/tasks.xml
new file mode 100644
index 0000000..a8572e6
--- /dev/null
+++ b/xdocs/tasks.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0"?>
+<!--
+ Licensed to the Apache Software Foundation (ASF) under one
+ or more contributor license agreements.  See the NOTICE file
+ distributed with this work for additional information
+ regarding copyright ownership.  The ASF licenses this file
+ to you under the Apache License, Version 2.0 (the
+ "License"); you may not use this file except in compliance
+ with the License.  You may obtain a copy of the License at
+
+   http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing,
+ software distributed under the License is distributed on an
+ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ KIND, either express or implied.  See the License for the
+ specific language governing permissions and limitations
+ under the License.
+-->
+<document>
+
+  <properties>
+    <title>Tasks</title>
+    <author email="epugh@upstate.com">Eric Pugh</author>
+  </properties>
+
+  <body>
+    <section name="Tasks">
+      <p>
+      	Lists of todos and ideas for future versions.
+      </p>
+
+      <subsection name="1.0">
+       <p>
+          <ul>
+           <li>
+              Need to test using the configuratio values.  Currently it just uses the default Classloader.
+            </li>
+           <li>
+              Document using different classloaders.
+            </li>
+          </ul>
+        </p>
+      </subsection>
+
+    </section>
+
+  </body>
+</document>