/*
* The contents of this file are subject to the Mozilla Public License
* Version 1.1 (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.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS"
* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
* the License for the specific language governing rights and limitations
* under the License.
*
* The Original Code is the Kowari Metadata Store.
*
* The Initial Developer of the Original Code is Plugged In Software Pty
* Ltd (http://www.pisoftware.com, mailto:info@pisoftware.com). Portions
* created by Plugged In Software Pty Ltd are Copyright (C) 2001,2002
* Plugged In Software Pty Ltd. All Rights Reserved.
*
* Contributor(s): N/A.
*
* [NOTE: The text of this Exhibit A may differ slightly from the text
* of the notices in the Source Code files of the Original Code. You
* should use the text of this Exhibit A rather than the text found in the
* Original Code Source Code for Your Modifications.]
*
*/
package org.mulgara.resolver;
// Java 2 standard packages
import java.beans.Beans;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Enumeration;
import javax.naming.NamingException;
// Java 2 enterprise packages
import javax.transaction.SystemException;
// Third party packages
import org.apache.log4j.Logger; // Apache Log4J
// Local packages
import org.mulgara.config.MulgaraConfig;
import org.mulgara.content.ContentHandler;
import org.mulgara.query.QueryException;
import org.mulgara.resolver.spi.*;
import org.mulgara.store.nodepool.NodePoolException;
import org.mulgara.store.stringpool.StringPoolException;
/**
* Construct and configure {@link Database} instances, based on a
* {@link MulgaraConfig} configuration.
*
* @created 2004-10-07
* @author <a href="http://www.pisoftware.com/raboczi">Simon Raboczi</a>
* @copyright ©2004 <a href="http://www.tucanatech.com/">Tucana Technology, Inc</a>
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
public abstract class DatabaseFactory {
/** Logger. */
private static final Logger logger = Logger.getLogger(DatabaseFactory.class.getName());
/**
* Creates a Database in a similar fashion to the stopgap constructor,
* however, this version contains a configuration object which will allow the
* server to configure the String and Node Pools as well as resolvers
* (including the system resolver) and content handlers.
*
* @param uri the unique {@link URI} naming this database, never
* <code>null</code>; this mustn't have a fragment part, because the
* fragment is used to represent models within the database
* @param directory an area on the filesystem for the database's use; if this
* is <code>null</code>, resolvers which require a filesystem can't be added
* @param config The configuration object that will be used to determine the
* missing class names
*
* @throws ConfigurationException
* @throws InitializerException
* @throws LocalizeException
* @throws NamingException
* @throws NodePoolException
* @throws QueryException
* @throws ResolverException
* @throws ResolverFactoryException
* @throws StringPoolException
* @throws URISyntaxException
*/
public static Database newDatabase(URI uri, File directory, MulgaraConfig config)
throws ConfigurationException, InitializerException, LocalizeException,
NamingException, NodePoolException, QueryException,
ResolverException, ResolverFactoryException,
SecurityAdapterFactoryException, StringPoolException,
SystemException, URISyntaxException {
Database database = new Database(
uri, // database name
new File[] {directory}, // persistence directory
uri, // security domain
new JotmTransactionManagerFactory(),
config.getTransactionTimeout(),
config.getIdleTimeout(),
config.getPersistentNodePoolFactory().getType(),
subdirs(directory, config.getPersistentNodePoolFactory().getDir()),
config.getPersistentStringPoolFactory().getType(),
subdirs(directory, config.getPersistentStringPoolFactory().getDir()),
config.getPersistentResolverFactory().getType(),
subdirs(directory, config.getPersistentResolverFactory().getDir()),
config.getTemporaryNodePoolFactory().getType(),
subdirs(directory, config.getTemporaryNodePoolFactory().getDir()),
config.getTemporaryStringPoolFactory().getType(),
subdirs(directory, config.getTemporaryStringPoolFactory().getDir()),
config.getTemporaryResolverFactory().getType(),
subdirs(directory, config.getTemporaryResolverFactory().getDir()),
config.getDefaultContentHandler().getType());
if (logger.isDebugEnabled()) logger.debug("Constructed database.");
configure(database, config);
if (logger.isDebugEnabled()) logger.debug("Configured database.");
return database;
}
static File[] subdirs(File parentDirectory, String childDirectory) throws ConfigurationException {
if (childDirectory == null) return null;
if (parentDirectory == null) {
throw new ConfigurationException("Can't configure directory " + childDirectory + "because there is no PersistencePath configured");
}
String[] children = childDirectory.split(File.pathSeparator);
File[] subdirs = new File[children.length];
for (int f = 0; f < children.length; f++) subdirs[f] = subdir(parentDirectory, children[f]);
return subdirs;
}
/**
* @param parentDirectory the absolute parent directory; this may be
* <code>null</code> if <var>childDirectory</var> is also <code>null</code>.
* Ignored if the child directory is absolute.
* @param childDirectory If relative, then relative to the parentDirectory, otherwise absolute.
* @return if <var>childDirectory</var> is non-<code>null</code> then the
* corresponding directory, otherwise <code>null</code>
* @throws ConfigurationException if <var>childDirectory</var> is not
* <code>null</code> and <var>parentDirectory</var> is <code>null</code>
*/
// TODO: Make this private once the 3-arg constructor is removed from
// Database.
static File subdir(File parentDirectory, String childDirectory) throws ConfigurationException {
if (childDirectory == null) return null;
if (parentDirectory == null) {
throw new ConfigurationException("Can't configure directory " + childDirectory + "because there is no PersistencePath configured");
}
if (childDirectory.startsWith("/")) return new File(childDirectory);
return new File(parentDirectory, childDirectory);
}
/**
* Add the additional resolver factories and content handlers specified in
* a database's configuration file.
* @param database an existing {@link Database} to configure
* @param config the configuration specifying the additional
* {@link ContentHandler} and {@link ResolverFactory} instances to add
* to the <var>database</var>
* @throws InitializerException if a configured {@link ResolverFactory} can't
* be added
* @throws SecurityAdapterFactoryException if a configured
* {@link SecurityAdapter} can't be created
*/
@SuppressWarnings("unchecked")
static void configure(Database database, MulgaraConfig config) throws InitializerException, SecurityAdapterFactoryException {
// Retrieve the enumeration of content handler classes
Enumeration<org.mulgara.config.ContentHandler> contentHandlers = config.enumerateContentHandler();
// Iterate through the enumeration and add the class names to the content
// handlers list
while (contentHandlers.hasMoreElements()) {
// Retrieve the next content handler class name
org.mulgara.config.ContentHandler contentHandler = contentHandlers.nextElement();
if (logger.isInfoEnabled()) logger.info("Loaded content handler: " + contentHandler.getType());
// Add the next content handler class name
database.addContentHandler(contentHandler.getType());
}
// Retrieve the enumeration of resolver factory classes
Enumeration<org.mulgara.config.ResolverFactory> resolverFactories = config.enumerateResolverFactory();
// Iterate through the enumeration and add the class names to the resolver
// factories list
while (resolverFactories.hasMoreElements()) {
// Retrieve the next resolver factory class name
org.mulgara.config.ResolverFactory resolverFactory = resolverFactories.nextElement();
if (logger.isInfoEnabled()) logger.info("Loaded resolver factory: " + resolverFactory.getType());
// Determine the persistence directory
File directory = null;
if (resolverFactory.getDir() != null && database.getRootDirectory() != null) {
directory = new File(database.getRootDirectory(), resolverFactory.getDir());
}
// Add the next resolver factory class name
database.addResolverFactory(resolverFactory.getType(), directory);
}
// Add the security adapters, if configured
Enumeration<org.mulgara.config.SecurityAdapterFactory> securityAdapterFactories = config.enumerateSecurityAdapterFactory();
while (securityAdapterFactories.hasMoreElements()) {
org.mulgara.config.SecurityAdapterFactory configSecurityAdapterFactory = securityAdapterFactories.nextElement();
// Instantiate the factory bean
SecurityAdapterFactory securityAdapterFactory;
try {
securityAdapterFactory = (SecurityAdapterFactory)Beans.instantiate(
database.getClass().getClassLoader(), configSecurityAdapterFactory.getType());
} catch (Exception e) {
throw new SecurityAdapterFactoryException("Unable to instantiate security adapter factory " + configSecurityAdapterFactory.getType(), e);
}
assert securityAdapterFactory != null;
// Add the security adapter
database.addSecurityAdapter(securityAdapterFactory);
}
Enumeration<org.mulgara.config.RuleLoader> ruleLoaders = config.enumerateRuleLoader();
while (ruleLoaders.hasMoreElements()) {
org.mulgara.config.RuleLoader ruleLoader = ruleLoaders.nextElement();
if (logger.isInfoEnabled()) logger.info("Loaded resolver factory: " + ruleLoader.getClass());
database.addRuleLoader(ruleLoader.getType());
}
}
}