blob: c3a4cf8166afd1a3fcf032ad587c1824a7c4fe55 [file] [log] [blame]
<?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>