<?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>
    <author email="tv@apache.org">Thomas Vandahl</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">
    <subsection name="Role Configuration">
      <source><![CDATA[
    <role
        name="org.apache.fulcrum.factory.FactoryService"
        shorthand="factory"
        default-class="org.apache.fulcrum.factory.DefaultFactoryService"/>
      ]]></source>
    </subsection>

    <subsection name="Component Configuration">
      <table>
        <tr>
          <th>Item</th>
          <th>Datatype</th>
          <th>Cardinality</th>
          <th>Description</th>
        </tr>
        <tr>
          <td>classloader</td>
          <td>String</td>
          <td>[0..n]</td>
          <td>
            A class loader. Class loaders will be tried in sequence when
            trying to create an object instance.
          </td>
        </tr>
        <tr>
          <td>object-factory</td>
          <td>Complex</td>
          <td>[0|1]</td>
          <td>
            The parent element for object factories. Sub-elements define
            factories for certain class names. You can define one
            <code>default</code> factory that will be used if no others
            match. See the configuration example below.
          </td>
        </tr>
      </table>
    </subsection>

    <subsection name="Component Configuration Example">
      <source><![CDATA[
    <factory>
        <classloader>java.net.URLClassLoader</classloader>
        <object-factory>
            <javax.xml.parsers.DocumentBuilder>
                org.foo.xml.DomBuilderFactory
            </javax.xml.parsers.DocumentBuilder>
            <default>
                org.some.default.Factory
            </default>
        </object-factory>
    </factory>
      ]]></source>
    </subsection>
  </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.factroy.FactoryException;
import org.apache.fulcrum.factory.Factory;

/**
 * A factory for instantiating DOM parsers.
 */
public class DomBuilderFactory implements Factory<DocumentBuilder>
{
    /**
     * The implementation of the factory.
     */
    private DocumentBuilderFactory factory;

    /**
     * Initializes the factory.
     */
    public void init(String className)
        throws FactoryException
    {
        factory = DocumentBuilderFactory.newInstance();
    }

    /**
     * Gets a DocumentBuilder instance.
     */
    public DocumentBuilder getInstance()
        throws FactoryException
    {
        try
        {
            return factory.newDocumentBuilder();
        }
        catch (ParserConfigurationException x)
        {
            throw new FactoryException(x);
        }
    }

    /**
     * Gets a DocumentBuilder instance.
     * The given loader is ignored.
     */
    public DocumentBuilder getInstance(ClassLoader loader)
        throws FactoryException
    {
        return getInstance();
    }

    /**
     * Gets a DocumentBuilder instance.
     * Constructor parameters are ignored.
     */
    public DocumentBuilder getInstance(Object[] params, String[] signature)
        throws FactoryException
    {
        return getInstance();
    }

    /**
     * Gets a DocumentBuilder instance.
     * The given loader and constructor parameters are ignored.
     */
    public DocumentBuilder getInstance(ClassLoader loader,
        Object[] params,
        String[] signature)
        throws FactoryException
    {
        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 the component 
      configuration like in the configuration example above before it can 
      be used.
    </p>

    <p>
    A DOM parser can now be instantiated with the following code fragment:
    </p>

    <source><![CDATA[
// Access the service singleton.
FactoryService service = (FactoryService)container.lookup(FactoryService.ROLE);

// Create a new DOM parser.
DocumentBuilder parser =
    service.getInstance("javax.xml.parsers.DocumentBuilder");
]]></source>

  </section>
</body>
</document>
