/*
* 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.server;
// Java 2 Standard Packages
import java.net.*;
import java.io.*;
// Third party packages
import org.apache.log4j.Logger; // Apache Log4J
// Locally written packages
import org.mulgara.config.MulgaraConfig;
import org.mulgara.server.SessionFactory;
import org.mulgara.util.ClasspathDesc;
import org.mulgara.util.ObjectUtil;
import java.lang.reflect.Constructor;
/**
* Used to obtain a {@link SessionFactory} instance using a configuration file
* or by method arguments.
*
* @created 2004-09-06
*
* @author <a href="mailto:robert.turner@tucanatech.com">Robert Turner</a>
*
* @version $Revision: 1.9 $
*
* @modified $Date: 2005/01/13 01:55:09 $
*
* @maintenanceAuthor $Author: raboczi $
*
* @company <A href="mailto:info@PIsoftware.com">Plugged In Software</A>
*
* @copyright © 2004 <A href="http://www.PIsoftware.com/">Plugged In
* Software Pty Ltd</A>
*
* @licence <a href="{@docRoot}/../../LICENCE">Mozilla Public License v1.1</a>
*/
public class SessionFactoryFactory {
/** Logger. This is named after the class. */
private static final Logger logger = Logger.getLogger(SessionFactoryFactory.class.getName());
/** Server name used if one is not configured */
public final static String DEFAULT_SERVER_NAME = "server1";
/** SessionFactory implementation */
private String className = "org.mulgara.store.xa.XADatabaseImpl";
/** default location of the config file */
private static final String CONFIG_PATH = "conf/mulgara-x-config.xml";
/** Config to use when creating new sessions */
private MulgaraConfig mulgaraConfig;
/**
* Default Constructor.
*
* @throws SessionFactoryException
*/
public SessionFactoryFactory() throws SessionFactoryException {
try {
// get a URL to the default server configuration file
URL defaultConfigURL = ClassLoader.getSystemResource(CONFIG_PATH);
if (defaultConfigURL == null) {
defaultConfigURL = ObjectUtil.getClassLoader(this).getResource(CONFIG_PATH);
if (defaultConfigURL == null) {
throw new SessionFactoryException(
"Unable to locate configuration file: " + defaultConfigURL +
" using the local or system classloader");
}
}
SessionFactoryConfiguration config =
this.getConfiguration(defaultConfigURL.openStream());
//check if the "className" has been configured or set as a system property.
String implementation = config.getClassName();
String tripleStoreImpl = System.getProperty("triple.store.implementation");
//try config first
if ( (implementation != null)
&& (!"".equals(implementation))) {
//use config file property
this.className = implementation;
}
else if ( (tripleStoreImpl != null)
&& (!"".equals(tripleStoreImpl))) {
//use system property
this.className = tripleStoreImpl;
}
} catch (IOException ioException) {
throw new SessionFactoryException("Could not open Configuration File.",
ioException);
}
}
/**
* Constructor. Sets the SessionFactory implementation to be used.
*
* @param className String
* @throws SessionFactoryException
*/
public SessionFactoryFactory(String className) throws SessionFactoryException {
this();
this.setSessionFactoryClass(className);
}
/**
* Sets the SessionFactory implementation to be instantiated.
*
* @param className String
*/
private void setSessionFactoryClass(String className) {
this.className = className;
}
/**
* Creates a new instance of the configured TripleStoreImplementation using
* the constructor specified by argTypes using args as constructor arguments.
*
* @param argTypes Class[]
* @param args Object[]
*
* @throws SessionFactoryException
* @return SessionFactory
*/
@SuppressWarnings("unchecked")
public SessionFactory getTripleStoreImplementation(String className,
Class<?>[] argTypes, Object[] args) throws SessionFactoryException {
try {
//load class
Class<? extends SessionFactory> storeClass = (Class<? extends SessionFactory>)Class.forName(className);
//get appropriate constructor
Constructor<? extends SessionFactory> constructor = storeClass.getConstructor(argTypes);
//instantiate
return constructor.newInstance(args);
} catch (ClassNotFoundException cnf) {
logger.error("Could not find TripleStoreImplementation class in: " +
ClasspathDesc.getPath());
throw new SessionFactoryException("Could not instantiate TripleStoreImplementation from configuration.", cnf);
} catch (Exception exception) {
throw new SessionFactoryException("Could not instantiate " +
"TripleStoreImplementation from " +
"configuration.", exception);
}
}
/**
* Obtain a {@link SessionFactory} instance. Using the default server URI and
* the tmp directory.
*
* @throws SessionFactoryException if a connection can't be established to
* the server
* @return SessionFactory
*/
public SessionFactory newSessionFactory()
throws SessionFactoryException {
URI serverURI = getDefaultServerURI();
File directory = new File(System.getProperty("java.io.tmpdir"));
return this.newSessionFactory(serverURI, directory);
}
/**
* Obtain a {@link SessionFactory} instance.
*
* @param serverURI the internet server to connect this session to.
* @param directory The directory to use for storage of triplestore data
*
* @throws SessionFactoryException if a connection can't be established to the server
* @return SessionFactory
*/
public SessionFactory newSessionFactory(URI serverURI, File directory)
throws SessionFactoryException {
//arguments to constructor
Class<?>[] argTypes = new Class [] {
serverURI.getClass(),
directory.getClass(),
mulgaraConfig.getClass()
};
Object[] args = new Object [] {
serverURI,
directory,
mulgaraConfig
};
return getTripleStoreImplementation(this.className, argTypes, args);
}
/**
* Obtain a {@link SessionFactory} instance.
*
* @param inStream stream containing the configuration
* @throws SessionFactoryException
* @return SessionFactory
*/
public SessionFactory newSessionFactory(InputStream inStream)
throws SessionFactoryException {
//parse the configuration file
SessionFactoryConfiguration config = getConfiguration(inStream);
//arguments to constructor
Class<?>[] argTypes = config.getConfigurationTypes();
Object[] args = config.getConfigurationObjects();
return getTripleStoreImplementation(config.getClassName(), argTypes, args);
}
/**
* Obtain a {@link SessionFactory} instance.
*
* @param uri URI
* @param directory File
* @param securityDomain URI
* @param persistentNodePoolFactoryClassName String
* @param persistentStringPoolFactoryClassName String
* @param temporaryNodePoolFactoryClassName String
* @param temporaryStringPoolFactoryClassName String
* @param systemResolverFactoryClassName String
* @throws SessionFactoryException
* @return SessionFactory
*/
public SessionFactory newSessionFactory(URI uri, File directory,
URI securityDomain, String persistentNodePoolFactoryClassName,
String persistentStringPoolFactoryClassName, String
temporaryNodePoolFactoryClassName, String
temporaryStringPoolFactoryClassName, String
systemResolverFactoryClassName)
throws SessionFactoryException {
//arguments to constructor
Class<?>[] argTypes = new Class[] {
uri.getClass(),
directory.getClass(),
securityDomain.getClass(),
persistentNodePoolFactoryClassName.getClass(),
persistentStringPoolFactoryClassName.getClass(),
temporaryNodePoolFactoryClassName.getClass(),
temporaryStringPoolFactoryClassName.getClass(),
systemResolverFactoryClassName.getClass()
};
Object[] args = new Object[] {
uri,
directory,
securityDomain,
persistentNodePoolFactoryClassName,
persistentStringPoolFactoryClassName,
temporaryNodePoolFactoryClassName,
temporaryStringPoolFactoryClassName,
systemResolverFactoryClassName
};
return getTripleStoreImplementation(this.className, argTypes, args);
}
/**
* Returns the default Server URI.
*
* <p>currently uses: rmi://localhost-address/DEFAULT_SERVER_NAME
*
* @return a Java RMI server {@link URI} for the local host, never
* <code>null</code>
* @throws SessionFactoryException if the server URI can't be composed
*/
public static URI getDefaultServerURI() throws SessionFactoryException {
return getServerURI(DEFAULT_SERVER_NAME);
}
/**
* Returns the local Server URI using the supplied name.
*
* <p>currently uses: rmi://localhost-address/serverName
*
* @param serverName the name of the server
* @return a Java RMI server {@link URI} for the local host, never
* <code>null</code>
* @throws SessionFactoryException if the server URI can't be composed
*/
public static URI getServerURI(String serverName) throws
SessionFactoryException {
//validate
if (serverName == null) {
throw new IllegalArgumentException("'serverName' argument is null.");
}
try {
//local host name
String localHost = InetAddress.getLocalHost().getCanonicalHostName();
//add '/' prefix (if not already there)
String name = serverName;
if (!name.startsWith("/")) {
name = "/" + name;
}
return new URI("rmi", localHost, name, null);
}
catch (UnknownHostException hostException) {
throw new SessionFactoryException("Couldn't determine local host name",
hostException);
}
catch (URISyntaxException uriException) {
throw new SessionFactoryException("Invalid local server URI.",
uriException);
}
}
/**
* Loads the configuration file and sets any (relevant) properties supplied.
*
* @param inStream a stream containing the configuration
* @throws SessionFactoryException
*/
private SessionFactoryConfiguration getConfiguration(InputStream inStream)
throws SessionFactoryException {
//validate
if (inStream == null) {
throw new IllegalArgumentException("Configuration File Input Stream is " +
"null.");
}
try {
//return value
SessionFactoryConfiguration sessionConfig = new
SessionFactoryConfiguration();
//create a configuration object from the stream
InputStreamReader reader = new InputStreamReader(inStream);
mulgaraConfig = MulgaraConfig.unmarshal(reader);
mulgaraConfig.validate();
//set configuration properties
//className
String storeImpl = mulgaraConfig.getTripleStoreImplementation();
if ((storeImpl != null)
&& (!"".equals(storeImpl))) {
sessionConfig.setClassName(storeImpl);
}
//server name (sets server URI)
String serverName = mulgaraConfig.getServerName();
if ((serverName != null)
&& (!"".equals(serverName))) {
URI uri = getServerURI(serverName);
sessionConfig.setServerURI(uri.toString());
}
//serverURI (overrides URI set for serverName)
String host = mulgaraConfig.getMulgaraHost();
if ((host != null)
&& (!"".equals(host))) {
sessionConfig.setServerURI(host);
}
//directory
String persistencePath = mulgaraConfig.getPersistencePath();
if ((persistencePath != null)
&& (!"".equals(persistencePath))) {
// '.' and "temp" are valid options
if (persistencePath.equalsIgnoreCase(".")) {
persistencePath = System.getProperty("user.dir");
}
else if (persistencePath.equalsIgnoreCase("temp")) {
persistencePath = System.getProperty("java.io.tmpdir");
}
sessionConfig.setDirectory(persistencePath);
}
return sessionConfig;
}
catch (org.exolab.castor.xml.MarshalException marshalException) {
// log the error
throw new SessionFactoryException("Castor Marshal Exception: ",
marshalException);
}
catch (org.exolab.castor.xml.ValidationException validException) {
// log the error
throw new SessionFactoryException("Unable to load configuration - ",
validException);
}
finally {
//clean up
try {
if (inStream != null) {
inStream.close();
}
}
catch (IOException ioException) {
//can't do anything
if (logger.isDebugEnabled()) {
logger.debug("Could not close file stream.", ioException);
}
}
}
}
}