/**
* Copyright 2007-2008 University Of Southern California
*
* Licensed 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.
*/
package edu.isi.pegasus.planner.catalog.work;
import edu.isi.pegasus.common.util.DynamicLoader;
import edu.isi.pegasus.common.util.CommonProperties;
import edu.isi.pegasus.planner.catalog.WorkCatalog;
import java.util.Properties;
import java.util.Enumeration;
import edu.isi.pegasus.planner.common.PegasusProperties;
/**
* This factory loads a work catalog, as specified by the properties.
* Each invocation of the factory will result in a new instance of a
* connection to the replica catalog.
*
* @author Karan Vahi
* @author Jens-S. Vöckler
* @version $Revision: 50 $
*
* @see org.griphyn.common.catalog.WorkCatalog
*/
public class WorkFactory{
/**
* Package to prefix "just" class names with.
*/
public static final String DEFAULT_PACKAGE = "edu.isi.pegasus.planner.catalog.work";
/**
* Connects the interface with the work catalog implementation. The
* choice of backend is configured through properties. This class is
* useful for non-singleton instances that may require changing
* properties.
*
* @param props is an instance of properties to use.
*
* @exception ClassNotFoundException if the schema for the database
* cannot be loaded. You might want to check your CLASSPATH, too.
* @exception NoSuchMethodException if the schema's constructor interface
* does not comply with the database driver API.
* @exception InstantiationException if the schema class is an abstract
* class instead of a concrete implementation.
* @exception IllegalAccessException if the constructor for the schema
* class it not publicly accessible to this package.
* @exception InvocationTargetException if the constructor of the schema
* throws an exception while being dynamically loaded.
*
* @see org.griphyn.common.util.CommonProperties
*/
static public WorkCatalog loadInstance( PegasusProperties props )
throws WorkFactoryException {
return loadInstance( props.getVDSProperties() );
}
/**
* Connects the interface with the work catalog implementation. The
* choice of backend is configured through properties. This class is
* useful for non-singleton instances that may require changing
* properties.
*
* @param props is an instance of properties to use.
*
* @exception ClassNotFoundException if the schema for the database
* cannot be loaded. You might want to check your CLASSPATH, too.
* @exception NoSuchMethodException if the schema's constructor interface
* does not comply with the database driver API.
* @exception InstantiationException if the schema class is an abstract
* class instead of a concrete implementation.
* @exception IllegalAccessException if the constructor for the schema
* class it not publicly accessible to this package.
* @exception InvocationTargetException if the constructor of the schema
* throws an exception while being dynamically loaded.
*
* @see org.griphyn.common.util.CommonProperties
*/
static public WorkCatalog loadInstance( CommonProperties props )
throws WorkFactoryException
{
// sanity check
if ( props == null ) throw new NullPointerException("invalid properties");
Properties connect = props.matchingSubset( WorkCatalog.c_prefix, false );
//get the default db driver properties in first pegasus.catalog.*.db.driver.*
Properties db = props.matchingSubset( WorkCatalog.DB_ALL_PREFIX, false );
//now overload with the work catalog specific db properties.
//pegasus.catalog.work.db.driver.*
db.putAll( props.matchingSubset( WorkCatalog.DB_PREFIX , false ) );
//to make sure that no confusion happens.
//add the db prefix to all the db properties
for( Enumeration e = db.propertyNames(); e.hasMoreElements(); ){
String key = (String)e.nextElement();
connect.put( "db." + key, db.getProperty( key ));
}
//put the driver property back into the DB property
// String driver = props.getProperty( WorkCatalog.DBDRIVER_PREFIX );
// if( driver == null ){ driver = props.getProperty( WorkCatalog.DBDRIVER_ALL_PREFIX ); }
// connect.put( "db.driver", driver );
// determine the class that implements the work catalog
return loadInstance( props.getProperty( WorkCatalog.c_prefix ),
connect );
}
/**
* Connects the interface with the work catalog implementation. The
* choice of backend is configured through properties. This class is
* useful for non-singleton instances that may require changing
* properties.
*
* @param props is an instance of properties to use.
*
* @exception ClassNotFoundException if the schema for the database
* cannot be loaded. You might want to check your CLASSPATH, too.
* @exception NoSuchMethodException if the schema's constructor interface
* does not comply with the database driver API.
* @exception InstantiationException if the schema class is an abstract
* class instead of a concrete implementation.
* @exception IllegalAccessException if the constructor for the schema
* class it not publicly accessible to this package.
* @exception InvocationTargetException if the constructor of the schema
* throws an exception while being dynamically loaded.
*
* @see org.griphyn.common.util.CommonProperties
*/
static private WorkCatalog loadInstance( String catalogImplementor,
Properties props )
throws WorkFactoryException
{
WorkCatalog result = null;
try{
if ( catalogImplementor == null )
throw new RuntimeException( "You need to specify the " +
WorkCatalog.c_prefix + " property" );
// syntactic sugar adds absolute class prefix
if ( catalogImplementor.indexOf('.') == -1 )
catalogImplementor = DEFAULT_PACKAGE + "." + catalogImplementor;
// POSTCONDITION: we have now a fully-qualified classname
DynamicLoader dl = new DynamicLoader( catalogImplementor );
result = (WorkCatalog) dl.instantiate( new Object[0] );
if ( ! result.connect( props ) )
throw new RuntimeException( "Unable to connect to work catalog implementation" );
}
catch( Exception e ) {
throw new WorkFactoryException(
" Unable to instantiate Work Catalog ",
catalogImplementor,
e );
}
// done
return result;
}
}