You are viewing a plain text version of this content. The canonical link for it is here.
Posted to torque-dev@db.apache.org by he...@apache.org on 2003/06/21 13:48:30 UTC

cvs commit: db-torque/src/java/org/apache/torque TorqueSingleton.java Torque.java

henning     2003/06/21 04:48:29

  Modified:    src/java/org/apache/torque Torque.java
  Added:       src/java/org/apache/torque TorqueSingleton.java
  Log:
  - Factor out all of the static methods from Torque into a Singleton class.
  - Remove all static code from Torque, replace it with Singleton calls.
  
  This should solve the init and sync problems that cropped up while playing
  with the Avalon Initialization of Torque.
  
  Revision  Changes    Path
  1.86      +81 -599   db-torque/src/java/org/apache/torque/Torque.java
  
  Index: Torque.java
  ===================================================================
  RCS file: /home/cvs/db-torque/src/java/org/apache/torque/Torque.java,v
  retrieving revision 1.85
  retrieving revision 1.86
  diff -u -r1.85 -r1.86
  --- Torque.java	20 Jun 2003 19:04:30 -0000	1.85
  +++ Torque.java	21 Jun 2003 11:48:29 -0000	1.86
  @@ -54,42 +54,26 @@
    * <http://www.apache.org/>.
    */
   
  -import java.io.IOException;
   import java.sql.Connection;
  -import java.sql.SQLException;
  -import java.util.ArrayList;
  -import java.util.Collections;
  -import java.util.HashMap;
  -import java.util.Iterator;
  -import java.util.List;
  -import java.util.Map;
   
   import org.apache.commons.configuration.Configuration;
  -import org.apache.commons.configuration.PropertiesConfiguration;
  -
  -import org.apache.commons.logging.Log;
  -import org.apache.commons.logging.LogFactory;
   
   import org.apache.stratum.lifecycle.Configurable;
   import org.apache.stratum.lifecycle.Disposable;
   import org.apache.stratum.lifecycle.Initializable;
   
   import org.apache.torque.adapter.DB;
  -import org.apache.torque.adapter.DBFactory;
  -import org.apache.torque.dsfactory.DataSourceFactory;
   import org.apache.torque.manager.AbstractBaseManager;
   import org.apache.torque.map.DatabaseMap;
  -import org.apache.torque.map.TableMap;
  -import org.apache.torque.oid.IDBroker;
  -import org.apache.torque.oid.IDGeneratorFactory;
  -import org.apache.torque.util.BasePeer;
   
   /**
  - * The implementation of Torque.
  + * A static facade wrapper around the Torque implementation (which is in
  + * {@link org.apache.torque.TorqueSingleton}).
    * <br/>
  - * <b>The stratum lifecycle interfaces are deprecated and will not be supported 
  - * in future versions on Torque. Instead you can use Torque as an avalon 
  - * component.</b>
  + * For historical reasons this class also contains a thin object which can
  + * be used to configure Torque with the Stratum Lifecycle. This is deprecated
  + * and will be removed in the future in favour of using Torque as an Avalon
  + * Component.
    *
    * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
    * @author <a href="mailto:magnus@handtolvur.is">Magn�s ��r Torfason</a>
  @@ -111,11 +95,6 @@
       public static final String DATABASE_DEFAULT = "database.default";
   
       /**
  -     * A constant for <code>default</code>.
  -     */
  -    private static final String DEFAULT_NAME = "default";
  -
  -    /**
        * A prefix for <code>Manager</code> properties in
        * the configuration.
        */
  @@ -132,250 +111,29 @@
        */
       public static final String CACHE_KEY = "manager.useCache";
   
  -    /**
  -     * The db name that is specified as the default in the property file
  -     */
  -    private static String defaultDBName;
  -
  -    /**
  -     * The global cache of database maps
  -     */
  -    private static Map dbMaps;
  -
  -    /**
  -     * The cache of DataSourceFactory's
  -     */
  -    private static Map dsFactoryMap;
  -
  -    /**
  -     * The cache of DB adapter keys
  -     */
  -    private static Map adapterMap;
  -
  -    /**
  -     * A repository of Manager instances.
  -     */
  -    protected static Map managers = new HashMap();
  -
  -    /**
  -     * The logging logger.
  -     */
  -    private static Log log = LogFactory.getLog(Torque.class);
  -
  -    /**
  -     * Torque-specific configuration.
  -     */
  -    private static Configuration configuration;
  -
  -    /**
  -     * flag to set to true once this class has been initialized
  -     */
  -    private static boolean isInit = false;
  -
  -    /**
  -     * Store mapbuilder classnames for peers that have been referenced prior
  -     * to Torque being initialized.  This can happen if torque om/peer objects
  -     * are serialized then unserialized prior to Torque being reinitialized.
  -     * This condition exists in a normal catalina restart.
  -     */
  -    private static List mapBuilders = null;
  -
  -    /**
  -     * Make sure that the map Builders List is always 
  -     * populated by fetching through a getter
  -     *
  -     * @return A List for the mapBuilders
  -     */
  -    private static List getMapBuilders()
  -    {
  -        if (mapBuilders == null)
  -        {
  -            mapBuilders = Collections.synchronizedList(new ArrayList());
  -        }
  -        return mapBuilders;
  -    }
  -
  -    /**
  -     * initialize Torque
  -     *
  -     * @see org.apache.stratum.lifecycle.Initializable
  -     * @throws TorqueException Any exceptions caught during processing will be
  -     *         rethrown wrapped into a TorqueException.
  -     */
  -    public void initialize() throws TorqueException
  -    {
  -        if (configuration == null)
  -        {
  -            throw new TorqueException("Torque cannot be initialized without "
  -                    + "a valid configuration. Please check the log files "
  -                    + "for further details.");
  -        }
  -
  -        // Now that we have dealt with processing the log4j properties
  -        // that may be contained in the configuration we will make the
  -        // configuration consist only of the remain torque specific
  -        // properties that are contained in the configuration. First
  -        // look for properties that are in the "torque" namespace.
  -        Configuration originalConf = configuration;
  -        configuration = configuration.subset("torque");
  -
  -        if (configuration == null || configuration.isEmpty())
  -        {
  -            // If there are no properties in the "torque" namespace
  -            // then try the "services.DatabaseService" namespace. This
  -            // will soon be deprecated.
  -            configuration = originalConf.subset("services.DatabaseService");
  -            if (configuration != null && !configuration.isEmpty())
  -            {
  -                /*
  -                logger.warn("Torque's 'services.DatabaseService.' " +
  -                              "configuration prefix has been deprecated in " +
  -                              "favor of the 'torque.' prefix");
  -                */
  -            }
  -            else
  -            {
  -                // Assume the original configuration already had any
  -                // prefixes stripped.
  -                configuration = originalConf;
  -            }
  -        }
  -
  -        dbMaps = new HashMap();
  -        initAdapters(configuration);
  -        initDataSourceFactories(configuration);
  -
  -        isInit = true;
  -        for (Iterator i = getMapBuilders().iterator(); i.hasNext();)
  -        {
  -            //this will add any maps in this builder to the proper database map
  -            BasePeer.getMapBuilder((String) i.next());
  -        }
  -        // any further mapBuilders will be called/built on demand
  -        mapBuilders = null;
  -
  -        // setup manager mappings
  -        initManagerMappings(configuration);
  -    }
  -
  -    /**
  -     *
  -     * @param configuration the Configuration representing the properties file
  -     * @throws TorqueException Any exceptions caught during processing will be
  -     *         rethrown wrapped into a TorqueException.
  +    /** 
  +     * This is a member variable of Torque objects created by the Stratum
  +     * lifecycle
        */
  -    private static final void initAdapters(Configuration configuration)
  -        throws TorqueException
  -    {
  -        log.debug("Starting initAdapters");
  -        adapterMap = new HashMap();
  -        Configuration c = configuration.subset("database");
  -        if (c != null)
  -        {
  -            try
  -            {
  -                Iterator i = c.getKeys();
  -                while (i.hasNext())
  -                {
  -                    String key = (String) i.next();
  -                    if (key.endsWith("adapter"))
  -                    {
  -                        String adapter = c.getString(key);
  -                        String handle = key.substring(0, key.indexOf('.'));
  -                        DB db = DBFactory.create(adapter);
  -                        // register the adapter for this name
  -                        adapterMap.put(handle, db);
  -                    }
  -                }
  -            }
  -            catch (Exception e)
  -            {
  -                log.error("", e);
  -                throw new TorqueException(e);
  -            }
  -        }
  -        else
  -        {
  -            log.warn("There were no adapters in the configuration.");
  -        }
  -    }
  +    private Configuration memberConfig = null;
   
       /**
  +     * C'tor for usage with the Stratum Lifecycle.
        *
  -     * @param configuration the Configuration representing the properties file
  -     * @throws TorqueException Any exceptions caught during processing will be
  -     *         rethrown wrapped into a TorqueException.
  +     * @todo Should be removed / made private once Stratum is removedP
        */
  -    private static void initDataSourceFactories(Configuration configuration)
  -        throws TorqueException
  +    public Torque()
       {
  -        log.debug("Starting initDSF");
  -        dsFactoryMap = new HashMap();
  -        Configuration c = configuration.subset("dsfactory");
  -        if (c != null)
  -        {
  -            try
  -            {
  -                Iterator i = c.getKeys();
  -                while (i.hasNext())
  -                {
  -                    String key = (String) i.next();
  -                    if (key.endsWith("factory"))
  -                    {
  -                        String classname = c.getString(key);
  -                        String handle = key.substring(0, key.indexOf('.'));
  -                        log.debug("handle: " + handle
  -                                + " DataSourceFactory: " + classname);
  -                        Class dsfClass = Class.forName(classname);
  -                        DataSourceFactory dsf =
  -                            (DataSourceFactory) dsfClass.newInstance();
  -                        dsf.initialize(c.subset(handle));
  -                        dsFactoryMap.put(handle, dsf);
  -                    }
  -                }
  -            }
  -            catch (Exception e)
  -            {
  -                log.error("", e);
  -                throw new TorqueException(e);
  -            }
  -        }
  -
  -        // As there might be a default database configured
  -        // to map "default" onto an existing datasource, we
  -        // must check, whether there _is_ really an entry for
  -        // the "default" in the dsFactoryMap or not. If it is
  -        // not, then add a dummy entry for the "default"
  -        //
  -        // Without this, you can't actually access the "default"
  -        // data-source, even if you have an entry like
  -        //
  -        // database.default = bookstore
  -        //
  -        // in your Torque.properties
  -        //
  -        String defaultDB = getDefaultDB();
  -
  -        if (dsFactoryMap.get(DEFAULT_NAME) == null
  -            && !defaultDB.equals(DEFAULT_NAME))
  -        {
  -            log.debug("Adding a dummy entry for "
  -                           + DEFAULT_NAME + ", mapped onto " + defaultDB);
  -            dsFactoryMap.put(DEFAULT_NAME, dsFactoryMap.get(defaultDB));
  -        }
       }
   
       /**
  -     * configure torque
  +     * Get the TorqueSingleton Instance.
        *
  -     * @param config Configuration
  -     * @see org.apache.stratum.lifecycle.Configurable
  -     * @throws TorqueException Any exceptions caught during processing will be
  -     *         rethrown wrapped into a TorqueException.
  +     * @return A Torque Singleton instance
        */
  -    public void configure(Configuration config) throws TorqueException
  +    private static TorqueSingleton getInstance()
       {
  -        configuration = config;
  +        return TorqueSingleton.getInstance();
       }
   
       /**
  @@ -388,127 +146,20 @@
       public static void init(String configFile)
           throws TorqueException
       {
  -        try
  -        {
  -            Configuration c = (Configuration)
  -                    new PropertiesConfiguration(configFile);
  -            init(c);
  -        }
  -        catch (IOException e)
  -        {
  -            throw new TorqueException(e);
  -        }
  +        getInstance().init(configFile);
       }
   
       /**
        * Initialization of Torque with a properties file.
        *
  -     * @param c The Torque configuration.
  -     * @throws TorqueException Any exceptions caught during processing will be
  -     *         rethrown wrapped into a TorqueException.
  -     */
  -    public static void init(Configuration c)
  -        throws TorqueException
  -    {
  -        Torque torque = new Torque();
  -        torque.configure(c);
  -        torque.initialize();
  -    }
  -
  -
  -    /**
  -     * Creates a mapping between classes and their manager classes.
  -     *
  -     * The mapping is built according to settings present in
  -     * properties file.  The entries should have the
  -     * following form:
  -     *
  -     * <pre>
  -     * torque.managed_class.com.mycompany.Myclass.manager= \
  -     *          com.mycompany.MyManagerImpl
  -     * services.managed_class.com.mycompany.Myotherclass.manager= \
  -     *          com.mycompany.MyOtherManagerImpl
  -     * </pre>
  -     *
  -     * <br>
  -     *
  -     * Generic ServiceBroker provides no Services.
  -     *
  -     * @param configuration the Configuration representing the properties file
  -     * @throws TorqueException Any exceptions caught during processing will be
  -     *         rethrown wrapped into a TorqueException.
  -     */
  -    protected static void initManagerMappings(Configuration configuration)
  -        throws TorqueException
  -    {
  -        int pref = MANAGER_PREFIX.length();
  -        int suff = MANAGER_SUFFIX.length();
  -
  -        Iterator keys = configuration.getKeys();
  -
  -        while (keys.hasNext())
  -        {
  -            String key = (String) keys.next();
  -
  -            if (key.startsWith(MANAGER_PREFIX)
  -                    && key.endsWith(MANAGER_SUFFIX))
  -            {
  -                String managedClassKey = key.substring(pref,
  -                        key.length() - suff);
  -                if (!managers.containsKey(managedClassKey))
  -                {
  -                    String managerClass = configuration.getString(key);
  -                    log.info("Added Manager for Class: " + managedClassKey
  -                                  + " -> " + managerClass);
  -                    try
  -                    {
  -                        initManager(managedClassKey, managerClass);
  -                    }
  -                    catch (TorqueException e)
  -                    {
  -                        // the exception thrown here seems to disappear.
  -                        // At least when initialized by Turbine, should find
  -                        // out why, but for now make sure it is noticed.
  -                        log.error("", e);
  -                        e.printStackTrace();
  -                        throw e;
  -                    }
  -                }
  -            }
  -        }
  -    }
  -
  -    /**
  -     * Initialize a manager
  -     *
  -     * @param name name of the manager
  -     * @param className name of the manager class
  +     * @param conf The Torque configuration.
        * @throws TorqueException Any exceptions caught during processing will be
        *         rethrown wrapped into a TorqueException.
        */
  -    private static synchronized void initManager(String name, String className)
  +    public static void init(Configuration conf)
           throws TorqueException
       {
  -        AbstractBaseManager manager = (AbstractBaseManager) managers.get(name);
  -
  -        if (manager == null)
  -        {
  -            if (className != null && className.length() != 0)
  -            {
  -                try
  -                {
  -                    manager = (AbstractBaseManager)
  -                        Class.forName(className).newInstance();
  -                    managers.put(name, manager);
  -                }
  -                catch (Exception e)
  -                {
  -                    throw new TorqueException(
  -                        "Could not instantiate manager associated with class: "
  -                        + name, e);
  -                }
  -            }
  -        }
  +        getInstance().init(conf);
       }
   
       /**
  @@ -518,17 +169,17 @@
        */
       public static boolean isInit()
       {
  -        return isInit;
  +        return getInstance().isInit();
       }
   
       /**
        * Sets the configuration for Torque and all dependencies.
        *
  -     * @param c the Configuration
  +     * @param conf the Configuration
        */
  -    public static void setConfiguration(Configuration c)
  +    public static void setConfiguration(Configuration conf)
       {
  -        configuration = c;
  +        getInstance().setConfiguration(conf);
       }
   
       /**
  @@ -538,7 +189,7 @@
        */
       public static Configuration getConfiguration()
       {
  -        return configuration;
  +        return getInstance().getConfiguration();
       }
   
       /**
  @@ -549,12 +200,7 @@
        */
       public static AbstractBaseManager getManager(String name)
       {
  -        AbstractBaseManager m = (AbstractBaseManager) managers.get(name);
  -        if (m == null)
  -        {
  -            log.error("No configured manager for key " + name + ".");
  -        }
  -        return m;
  +        return getInstance().getManager(name);
       }
   
       /**
  @@ -568,35 +214,7 @@
       public static AbstractBaseManager getManager(String name,
               String defaultClassName)
       {
  -        AbstractBaseManager m = (AbstractBaseManager) managers.get(name);
  -        if (m == null)
  -        {
  -            log.debug("Added late Manager mapping for Class: "
  -                           + name + " -> " + defaultClassName);
  -
  -            try
  -            {
  -                initManager(name, defaultClassName);
  -            }
  -            catch (TorqueException e)
  -            {
  -                log.error(e.getMessage(), e);
  -            }
  -
  -            // Try again now that the default manager should be in the map
  -            m = (AbstractBaseManager) managers.get(name);
  -        }
  -
  -        return m;
  -    }
  -
  -    /**
  -     * Shuts down the service, Lifecycle style
  -     *
  -     */
  -    public void dispose()
  -    {
  -        shutdown();
  +        return getInstance().getManager(name, defaultClassName);
       }
   
       /**
  @@ -607,19 +225,7 @@
        */
       public static void shutdown()
       {
  -        if (dbMaps != null)
  -        {
  -            Iterator maps = dbMaps.values().iterator();
  -            while (maps.hasNext())
  -            {
  -                DatabaseMap map = (DatabaseMap) maps.next();
  -                IDBroker idBroker = map.getIDBroker();
  -                if (idBroker != null)
  -                {
  -                    idBroker.stop();
  -                }
  -            }
  -        }
  +        getInstance().shutdown();
       }
   
       /**
  @@ -632,7 +238,7 @@
       public static DatabaseMap getDatabaseMap()
           throws TorqueException
       {
  -        return getDatabaseMap(getDefaultDB());
  +        return getInstance().getDatabaseMap();
       }
   
       /**
  @@ -648,73 +254,7 @@
       public static DatabaseMap getDatabaseMap(String name)
           throws TorqueException
       {
  -        if (name == null)
  -        {
  -            throw new TorqueException ("DatabaseMap name was null!");
  -        }
  -
  -        if (dbMaps == null)
  -        {
  -            throw new TorqueException("Torque was not initialized properly.");
  -        }
  -
  -        synchronized (dbMaps)
  -        {
  -            DatabaseMap map = (DatabaseMap) dbMaps.get(name);
  -            if (map == null)
  -            {
  -                // Still not there.  Create and add.
  -                map = initDatabaseMap(name);
  -            }
  -            return map;
  -        }
  -    }
  -
  -    /**
  -     * Creates and initializes the mape for the named database.
  -     * Assumes that <code>dbMaps</code> member is sync'd.
  -     *
  -     * @param name The name of the database to map.
  -     * @return The desired map.
  -     * @throws TorqueException Any exceptions caught during processing will be
  -     *         rethrown wrapped into a TorqueException.
  -     */
  -    private static final DatabaseMap initDatabaseMap(String name)
  -        throws TorqueException
  -    {
  -        DatabaseMap map = new DatabaseMap(name);
  -
  -        // Add info about IDBroker's table.
  -        setupIdTable(map);
  -
  -        // Setup other ID generators for this map.
  -        try
  -        {
  -            String key = getDatabaseProperty(name, "driver");
  -            if (key == null || key.length() == 0)
  -            {
  -                key = getDatabaseProperty(name, "adapter");
  -            }
  -            DB db = DBFactory.create(key);
  -            for (int i = 0; i < IDGeneratorFactory.ID_GENERATOR_METHODS.length;
  -                 i++)
  -            {
  -                map.addIdGenerator(IDGeneratorFactory.ID_GENERATOR_METHODS[i],
  -                                   IDGeneratorFactory.create(db));
  -            }
  -        }
  -        catch (java.lang.InstantiationException e)
  -        {
  -            throw new TorqueException(e);
  -        }
  -
  -        // Avoid possible ConcurrentModificationException by
  -        // constructing a copy of dbMaps.
  -        Map newMaps = new HashMap(dbMaps);
  -        newMaps.put(name, map);
  -        dbMaps = newMaps;
  -
  -        return map;
  +        return getInstance().getDatabaseMap(name);
       }
   
       /**
  @@ -724,43 +264,7 @@
        */
       public static void registerMapBuilder(String className)
       {
  -        getMapBuilders().add(className);
  -    }
  -
  -    /**
  -     * Returns the specified property of the given database, or the empty
  -     * string if no value is set for the property.
  -     *
  -     * @param db   The name of the database whose property to get.
  -     * @param prop The name of the property to get.
  -     * @return     The property's value.
  -     */
  -    private static String getDatabaseProperty(String db, String prop)
  -    {
  -        return configuration.getString(new StringBuffer("database.")
  -                .append(db)
  -                .append('.')
  -                .append(prop)
  -                .toString(), "");
  -    }
  -
  -    /**
  -     * Setup IDBroker's table information within given database map.
  -     *
  -     * This method should be called on all new database map to ensure that
  -     * IDBroker functionality is available in all databases used by the
  -     * application.
  -     *
  -     * @param map the DataBaseMap to setup.
  -     */
  -    private static final void setupIdTable(DatabaseMap map)
  -    {
  -        map.setIdTable("ID_TABLE");
  -        TableMap tMap = map.getIdTable();
  -        tMap.addPrimaryKey("ID_TABLE_ID", new Integer(0));
  -        tMap.addColumn("TABLE_NAME", new String(""));
  -        tMap.addColumn("NEXT_ID", new Integer(0));
  -        tMap.addColumn("QUANTITY", new Integer(0));
  +        getInstance().registerMapBuilder(className);
       }
   
       /**
  @@ -773,7 +277,7 @@
       public static Connection getConnection()
           throws TorqueException
       {
  -        return getConnection(getDefaultDB());
  +        return getInstance().getConnection();
       }
   
       /**
  @@ -786,27 +290,7 @@
       public static Connection getConnection(String name)
           throws TorqueException
       {
  -        Connection con = null;
  -        DataSourceFactory dsf = null;
  -        try
  -        {
  -            dsf = (DataSourceFactory) dsFactoryMap.get(name);
  -            con = dsf.getDataSource().getConnection();
  -        }
  -        catch (Exception e)
  -        {
  -             if (dsf == null && e instanceof NullPointerException)
  -             {
  -                 throw new NullPointerException(
  -                     "There was no DataSourceFactory "
  -                     + "configured for the connection " + name);
  -             }
  -             else
  -             {
  -                 throw new TorqueException(e);
  -             }
  -        }
  -        return con;
  +        return getInstance().getConnection(name);
       }
   
       /**
  @@ -825,29 +309,8 @@
               String password)
               throws TorqueException
       {
  -        Connection con = null;
  -        DataSourceFactory dsf = null;
  -        try
  -        {
  -            dsf = (DataSourceFactory) dsFactoryMap.get(name);
  -            con = dsf.getDataSource().getConnection(username, password);
  -        }
  -        catch (Exception e)
  -        {
  -             if (dsf == null && e instanceof NullPointerException)
  -             {
  -                 throw new NullPointerException(
  -                         "There was no DataSourceFactory "
  -                         + "configured for the connection " + name);
  -             }
  -             else
  -             {
  -                 throw new TorqueException(e);
  -             }
  -        }
  -        return con;
  +        return getInstance().getConnection(name, username, password);
       }
  -
       /**
        * Returns database adapter for a specific connection pool.
        *
  @@ -858,11 +321,9 @@
        */
       public static DB getDB(String name) throws TorqueException
       {
  -        return (DB) adapterMap.get(name);
  +        return getInstance().getDB(name);
       }
   
  -    ///////////////////////////////////////////////////////////////////////////
  -
       /**
        * Returns the name of the default database.
        *
  @@ -870,18 +331,7 @@
        */
       public static String getDefaultDB()
       {
  -        if (configuration == null)
  -        {
  -            return DEFAULT_NAME;
  -        }
  -        else if (defaultDBName == null)
  -        {
  -            // Determine default database name.
  -            defaultDBName =
  -                configuration.getString(DATABASE_DEFAULT, DEFAULT_NAME).trim();
  -        }
  -
  -        return defaultDBName;
  +        return getInstance().getDefaultDB();
       }
   
       /**
  @@ -891,16 +341,48 @@
        */
       public static void closeConnection(Connection con)
       {
  -        if (con != null)
  -        {
  -            try
  -            {
  -                con.close();
  -            }
  -            catch (SQLException e)
  -            {
  -                log.error("Error occured while closing connection.", e);
  -            }
  -        }
  +        getInstance().closeConnection(con);
  +    }
  +
  +    /*
  +     * ========================================================================
  +     *
  +     * Stratum Lifecycle Interface (deprecated)
  +     *
  +     * ========================================================================
  +     */
  +
  +    /**
  +     * configure torque
  +     *
  +     * @param conf Configuration
  +     * @see org.apache.stratum.lifecycle.Configurable
  +     * @throws TorqueException Any exceptions caught during processing will be
  +     *         rethrown wrapped into a TorqueException.
  +     */
  +    public void configure(Configuration conf) throws TorqueException
  +    {
  +        this.memberConfig = conf;
  +    }
  +
  +    /**
  +     * initialize Torque
  +     *
  +     * @see org.apache.stratum.lifecycle.Initializable
  +     * @throws TorqueException Any exceptions caught during processing will be
  +     *         rethrown wrapped into a TorqueException.
  +     */
  +    public void initialize() throws TorqueException
  +    {
  +        getInstance().init(memberConfig);
  +    }
  +
  +    /**
  +     * Shuts down the service, Lifecycle style
  +     *
  +     */
  +    public void dispose()
  +    {
  +        getInstance().shutdown();
       }
   }
  
  
  
  1.1                  db-torque/src/java/org/apache/torque/TorqueSingleton.java
  
  Index: TorqueSingleton.java
  ===================================================================
  package org.apache.torque;
  
  /* ====================================================================
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution,
   *    if any, must include the following acknowledgment:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowledgment may appear in the software itself,
   *    if and wherever such third-party acknowledgments normally appear.
   *
   * 4. The names "Apache" and "Apache Software Foundation" and
   *    "Apache Turbine" must not be used to endorse or promote products
   *    derived from this software without prior written permission. For
   *    written permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache",
   *    "Apache Turbine", nor may "Apache" appear in their name, without
   *    prior written permission of the Apache Software Foundation.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  import java.io.IOException;
  import java.sql.Connection;
  import java.sql.SQLException;
  import java.util.ArrayList;
  import java.util.Collections;
  import java.util.HashMap;
  import java.util.Iterator;
  import java.util.List;
  import java.util.Map;
  
  import org.apache.commons.configuration.Configuration;
  import org.apache.commons.configuration.PropertiesConfiguration;
  
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
  
  import org.apache.torque.adapter.DB;
  import org.apache.torque.adapter.DBFactory;
  import org.apache.torque.dsfactory.DataSourceFactory;
  import org.apache.torque.manager.AbstractBaseManager;
  import org.apache.torque.map.DatabaseMap;
  import org.apache.torque.map.TableMap;
  import org.apache.torque.oid.IDBroker;
  import org.apache.torque.oid.IDGeneratorFactory;
  import org.apache.torque.util.BasePeer;
  
  /**
   * The implementation of Torque.
   * <br/>
   * This is a singleton pattern so that Torque works both as a Avalon component
   * and as a standalone application by using the Torque facade.
   *
   *
   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
   * @author <a href="mailto:magnus@handtolvur.is">Magn�s ��r Torfason</a>
   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
   * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
   * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
   * @author <a href="mailto:kschrader@karmalab.org">Kurt Schrader</a>
   * @version $Id: TorqueSingleton.java,v 1.1 2003/06/21 11:48:29 henning Exp $
   */
  public class TorqueSingleton
  {
      /** Logging */
      private static Log log = LogFactory.getLog(TorqueSingleton.class);
  
      /** A constant for <code>default</code>. */
      private static final String DEFAULT_NAME = "default";
  
      /**
       * The db name that is specified as the default in the property file
       */
      private String defaultDBName;
  
      /**
       * The global cache of database maps
       */
      private Map dbMaps;
  
      /**
       * The cache of DataSourceFactory's
       */
      private Map dsFactoryMap;
  
      /**
       * The cache of DB adapter keys
       */
      private Map adapterMap;
  
      /** A repository of Manager instances. */
      private Map managers;
  
      /**
       * Torque-specific configuration.
       */
      private Configuration conf;
  
      /**
       * flag to set to true once this class has been initialized
       */
      private boolean isInit = false;
  
      /**
       * Store mapbuilder classnames for peers that have been referenced prior
       * to Torque being initialized.  This can happen if torque om/peer objects
       * are serialized then unserialized prior to Torque being reinitialized.
       * This condition exists in a normal catalina restart.
       */
      private List mapBuilders = null;
  
      /*
       * ========================================================================
       *
       * Singleton Pattern
       *
       * ========================================================================
       */
  
      /** The only instance in this class */
      private static TorqueSingleton torqueSingleton = null;
  
      /**
       * C'tor
       */
      private TorqueSingleton()
      {
          mapBuilders = Collections.synchronizedList(new ArrayList());
          managers = new HashMap();
          isInit = false;
      }
  
      /**
       * Fetch the Torque Instance from the Singleton
       *
       * @return The only TorqueSingleton Instance
       */
  
      public static synchronized TorqueSingleton getInstance()
      {
          if (torqueSingleton == null)
          {
              torqueSingleton = new TorqueSingleton();
          }
          return torqueSingleton;
      }
          
      /**
       * initialize Torque
       *
       * @see org.apache.stratum.lifecycle.Initializable
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      private void initialize() throws TorqueException
      {
          if (conf == null)
          {
              throw new TorqueException("Torque cannot be initialized without "
                      + "a valid configuration. Please check the log files "
                      + "for further details.");
          }
  
          // Now that we have dealt with processing the log4j properties
          // that may be contained in the configuration we will make the
          // configuration consist only of the remain torque specific
          // properties that are contained in the configuration. First
          // look for properties that are in the "torque" namespace.
          Configuration originalConf = conf;
          conf = conf.subset("torque");
  
          if (conf == null || conf.isEmpty())
          {
              // If there are no properties in the "torque" namespace
              // then try the "services.DatabaseService" namespace. This
              // is deprecated and will be removed t
              conf = originalConf.subset("services.DatabaseService");
              if (conf != null && !conf.isEmpty())
              {
                  /*
                    logger.warn("Torque's 'services.DatabaseService.' " +
                    "configuration prefix has been deprecated in " +
                    "favor of the 'torque.' prefix");
                  */
              }
              else
              {
                  // Assume the original configuration already had any
                  // prefixes stripped.
                  conf = originalConf;
              }
          }
  
          dbMaps = new HashMap();
          initAdapters(conf);
          initDataSourceFactories(conf);
  
          isInit = true;
          for (Iterator i = mapBuilders.iterator(); i.hasNext();)
          {
              //this will add any maps in this builder to the proper database map
              BasePeer.getMapBuilder((String) i.next());
          }
          // any further mapBuilders will be called/built on demand
          mapBuilders = null;
  
          // setup manager mappings
          initManagerMappings(conf);
      }
  
      /**
       *
       * @param conf the Configuration representing the properties file
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      private final void initAdapters(Configuration conf)
              throws TorqueException
      {
          log.debug("Starting initAdapters");
          adapterMap = new HashMap();
          Configuration c = conf.subset("database");
          if (c != null)
          {
              try
              {
                  Iterator i = c.getKeys();
                  while (i.hasNext())
                  {
                      String key = (String) i.next();
                      if (key.endsWith("adapter"))
                      {
                          String adapter = c.getString(key);
                          String handle = key.substring(0, key.indexOf('.'));
                          DB db = DBFactory.create(adapter);
                          // register the adapter for this name
                          adapterMap.put(handle, db);
                      }
                  }
              }
              catch (Exception e)
              {
                  log.error("", e);
                  throw new TorqueException(e);
              }
          }
          else
          {
              log.warn("There were no adapters in the configuration.");
          }
      }
  
      /**
       *
       * @param conf the Configuration representing the properties file
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      private void initDataSourceFactories(Configuration conf)
              throws TorqueException
      {
          log.debug("Starting initDSF");
          dsFactoryMap = new HashMap();
          Configuration c = conf.subset("dsfactory");
          if (c != null)
          {
              try
              {
                  Iterator i = c.getKeys();
                  while (i.hasNext())
                  {
                      String key = (String) i.next();
                      if (key.endsWith("factory"))
                      {
                          String classname = c.getString(key);
                          String handle = key.substring(0, key.indexOf('.'));
                          log.debug("handle: " + handle
                                  + " DataSourceFactory: " + classname);
                          Class dsfClass = Class.forName(classname);
                          DataSourceFactory dsf =
                                  (DataSourceFactory) dsfClass.newInstance();
                          dsf.initialize(c.subset(handle));
                          dsFactoryMap.put(handle, dsf);
                      }
                  }
              }
              catch (Exception e)
              {
                  log.error("", e);
                  throw new TorqueException(e);
              }
          }
  
          // As there might be a default database configured
          // to map "default" onto an existing datasource, we
          // must check, whether there _is_ really an entry for
          // the "default" in the dsFactoryMap or not. If it is
          // not, then add a dummy entry for the "default"
          //
          // Without this, you can't actually access the "default"
          // data-source, even if you have an entry like
          //
          // database.default = bookstore
          //
          // in your Torque.properties
          //
          String defaultDB = getDefaultDB();
  
          if (dsFactoryMap.get(DEFAULT_NAME) == null
                  && !defaultDB.equals(DEFAULT_NAME))
          {
              log.debug("Adding a dummy entry for "
                      + DEFAULT_NAME + ", mapped onto " + defaultDB);
              dsFactoryMap.put(DEFAULT_NAME, dsFactoryMap.get(defaultDB));
          }
      }
  
      /**
       * Initialization of Torque with a properties file.
       *
       * @param configFile The absolute path to the configuration file.
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      public void init(String configFile)
              throws TorqueException
      {
          try
          {
              Configuration conf = (Configuration)
                      new PropertiesConfiguration(configFile);
              init(conf);
          }
          catch (IOException e)
          {
              throw new TorqueException(e);
          }
      }
  
      /**
       * Initialization of Torque with a properties file.
       *
       * @param conf The Torque configuration.
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      public void init(Configuration conf)
              throws TorqueException
      {
          setConfiguration(conf);
          initialize();
      }
  
  
      /**
       * Creates a mapping between classes and their manager classes.
       *
       * The mapping is built according to settings present in
       * properties file.  The entries should have the
       * following form:
       *
       * <pre>
       * torque.managed_class.com.mycompany.Myclass.manager= \
       *          com.mycompany.MyManagerImpl
       * services.managed_class.com.mycompany.Myotherclass.manager= \
       *          com.mycompany.MyOtherManagerImpl
       * </pre>
       *
       * <br>
       *
       * Generic ServiceBroker provides no Services.
       *
       * @param conf the Configuration representing the properties file
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      protected void initManagerMappings(Configuration conf)
              throws TorqueException
      {
          int pref = Torque.MANAGER_PREFIX.length();
          int suff = Torque.MANAGER_SUFFIX.length();
  
          Iterator keys = conf.getKeys();
  
          while (keys.hasNext())
          {
              String key = (String) keys.next();
  
              if (key.startsWith(Torque.MANAGER_PREFIX)
                      && key.endsWith(Torque.MANAGER_SUFFIX))
              {
                  String managedClassKey = key.substring(pref,
                          key.length() - suff);
                  if (!managers.containsKey(managedClassKey))
                  {
                      String managerClass = conf.getString(key);
                      log.info("Added Manager for Class: " + managedClassKey
                              + " -> " + managerClass);
                      try
                      {
                          initManager(managedClassKey, managerClass);
                      }
                      catch (TorqueException e)
                      {
                          // the exception thrown here seems to disappear.
                          // At least when initialized by Turbine, should find
                          // out why, but for now make sure it is noticed.
                          log.error("", e);
                          e.printStackTrace();
                          throw e;
                      }
                  }
              }
          }
      }
  
      /**
       * Initialize a manager
       *
       * @param name name of the manager
       * @param className name of the manager class
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      private synchronized void initManager(String name, String className)
              throws TorqueException
      {
          AbstractBaseManager manager = (AbstractBaseManager) managers.get(name);
  
          if (manager == null)
          {
              if (className != null && className.length() != 0)
              {
                  try
                  {
                      manager = (AbstractBaseManager)
                              Class.forName(className).newInstance();
                      managers.put(name, manager);
                  }
                  catch (Exception e)
                  {
                      throw new TorqueException("Could not instantiate "
                              + "manager associated with class: "
                              + name, e);
                  }
              }
          }
      }
  
      /**
       * Determine whether Torque has already been initialized.
       *
       * @return true if Torque is already initialized
       */
      public boolean isInit()
      {
          return isInit;
      }
  
      /**
       * Sets the configuration for Torque and all dependencies.
       *
       * @param conf the Configuration
       */
      public void setConfiguration(Configuration conf)
      {
          this.conf = conf;
      }
  
      /**
       * Get the configuration for this component.
       *
       * @return the Configuration
       */
      public Configuration getConfiguration()
      {
          return conf;
      }
  
      /**
       * This method returns a Manager for the given name.
       *
       * @param name name of the manager
       * @return a Manager
       */
      public AbstractBaseManager getManager(String name)
      {
          AbstractBaseManager m = (AbstractBaseManager) managers.get(name);
          if (m == null)
          {
              log.error("No configured manager for key " + name + ".");
          }
          return m;
      }
  
      /**
       * This methods returns either the Manager from the configuration file,
       * or the default one provided by the generated code.
       *
       * @param name name of the manager
       * @param defaultClassName the class to use if name has not been configured
       * @return a Manager
       */
      public AbstractBaseManager getManager(String name,
              String defaultClassName)
      {
          AbstractBaseManager m = (AbstractBaseManager) managers.get(name);
          if (m == null)
          {
              log.debug("Added late Manager mapping for Class: "
                      + name + " -> " + defaultClassName);
  
              try
              {
                  initManager(name, defaultClassName);
              }
              catch (TorqueException e)
              {
                  log.error(e.getMessage(), e);
              }
  
              // Try again now that the default manager should be in the map
              m = (AbstractBaseManager) managers.get(name);
          }
  
          return m;
      }
  
      /**
       * Shuts down the service.
       *
       * This method halts the IDBroker's daemon thread in all of
       * the DatabaseMap's.
       */
      public void shutdown()
      {
          if (dbMaps != null)
          {
              Iterator maps = dbMaps.values().iterator();
              while (maps.hasNext())
              {
                  DatabaseMap map = (DatabaseMap) maps.next();
                  IDBroker idBroker = map.getIDBroker();
                  if (idBroker != null)
                  {
                      idBroker.stop();
                  }
              }
          }
      }
  
      /**
       * Returns the default database map information.
       *
       * @return A DatabaseMap.
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      public DatabaseMap getDatabaseMap()
              throws TorqueException
      {
          return getDatabaseMap(getDefaultDB());
      }
  
      /**
       * Returns the database map information. Name relates to the name
       * of the connection pool to associate with the map.
       *
       * @param name The name of the database corresponding to the
       *        <code>DatabaseMap</code> to retrieve.
       * @return The named <code>DatabaseMap</code>.
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      public DatabaseMap getDatabaseMap(String name)
              throws TorqueException
      {
          if (name == null)
          {
              throw new TorqueException ("DatabaseMap name was null!");
          }
  
          if (dbMaps == null)
          {
              throw new TorqueException("Torque was not initialized properly.");
          }
  
          synchronized (dbMaps)
          {
              DatabaseMap map = (DatabaseMap) dbMaps.get(name);
              if (map == null)
              {
                  // Still not there.  Create and add.
                  map = initDatabaseMap(name);
              }
              return map;
          }
      }
  
      /**
       * Creates and initializes the mape for the named database.
       * Assumes that <code>dbMaps</code> member is sync'd.
       *
       * @param name The name of the database to map.
       * @return The desired map.
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      private final DatabaseMap initDatabaseMap(String name)
              throws TorqueException
      {
          DatabaseMap map = new DatabaseMap(name);
  
          // Add info about IDBroker's table.
          setupIdTable(map);
  
          // Setup other ID generators for this map.
          try
          {
              String key = getDatabaseProperty(name, "driver");
              if (key == null || key.length() == 0)
              {
                  key = getDatabaseProperty(name, "adapter");
              }
              DB db = DBFactory.create(key);
              for (int i = 0; i < IDGeneratorFactory.ID_GENERATOR_METHODS.length;
                   i++)
              {
                  map.addIdGenerator(IDGeneratorFactory.ID_GENERATOR_METHODS[i],
                          IDGeneratorFactory.create(db));
              }
          }
          catch (java.lang.InstantiationException e)
          {
              throw new TorqueException(e);
          }
  
          // Avoid possible ConcurrentModificationException by
          // constructing a copy of dbMaps.
          Map newMaps = new HashMap(dbMaps);
          newMaps.put(name, map);
          dbMaps = newMaps;
  
          return map;
      }
  
      /**
       * Register a MapBuilder
       *
       * @param className the MapBuilder
       */
      public void registerMapBuilder(String className)
      {
          mapBuilders.add(className);
      }
  
      /**
       * Returns the specified property of the given database, or the empty
       * string if no value is set for the property.
       *
       * @param db   The name of the database whose property to get.
       * @param prop The name of the property to get.
       * @return     The property's value.
       */
      private String getDatabaseProperty(String db, String prop)
      {
          return conf.getString(new StringBuffer("database.")
                  .append(db)
                  .append('.')
                  .append(prop)
                  .toString(), "");
      }
  
      /**
       * Setup IDBroker's table information within given database map.
       *
       * This method should be called on all new database map to ensure that
       * IDBroker functionality is available in all databases used by the
       * application.
       *
       * @param map the DataBaseMap to setup.
       */
      private final void setupIdTable(DatabaseMap map)
      {
          map.setIdTable("ID_TABLE");
          TableMap tMap = map.getIdTable();
          tMap.addPrimaryKey("ID_TABLE_ID", new Integer(0));
          tMap.addColumn("TABLE_NAME", new String(""));
          tMap.addColumn("NEXT_ID", new Integer(0));
          tMap.addColumn("QUANTITY", new Integer(0));
      }
  
      /**
       * This method returns a Connection from the default pool.
       *
       * @return The requested connection.
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      public Connection getConnection()
              throws TorqueException
      {
          return getConnection(getDefaultDB());
      }
  
      /**
       *
       * @param name The database name.
       * @return a database connection
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      public Connection getConnection(String name)
              throws TorqueException
      {
          Connection con = null;
          DataSourceFactory dsf = null;
          try
          {
              dsf = (DataSourceFactory) dsFactoryMap.get(name);
              con = dsf.getDataSource().getConnection();
          }
          catch (Exception e)
          {
              if (dsf == null && e instanceof NullPointerException)
              {
                  throw new NullPointerException(
                          "There was no DataSourceFactory "
                          + "configured for the connection " + name);
              }
              else
              {
                  throw new TorqueException(e);
              }
          }
          return con;
      }
  
      /**
       * This method returns a Connecton using the given parameters.
       * You should only use this method if you need user based access to the
       * database!
       *
       * @param name The database name.
       * @param username The name of the database user.
       * @param password The password of the database user.
       * @return A Connection.
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      public Connection getConnection(String name, String username,
              String password)
              throws TorqueException
      {
          Connection con = null;
          DataSourceFactory dsf = null;
          try
          {
              dsf = (DataSourceFactory) dsFactoryMap.get(name);
              con = dsf.getDataSource().getConnection(username, password);
          }
          catch (Exception e)
          {
              if (dsf == null && e instanceof NullPointerException)
              {
                  throw new NullPointerException(
                          "There was no DataSourceFactory "
                          + "configured for the connection " + name);
              }
              else
              {
                  throw new TorqueException(e);
              }
          }
          return con;
      }
  
      /**
       * Returns database adapter for a specific connection pool.
       *
       * @param name A pool name.
       * @return The corresponding database adapter.
       * @throws TorqueException Any exceptions caught during processing will be
       *         rethrown wrapped into a TorqueException.
       */
      public DB getDB(String name) throws TorqueException
      {
          return (DB) adapterMap.get(name);
      }
  
      ///////////////////////////////////////////////////////////////////////////
  
      /**
       * Returns the name of the default database.
       *
       * @return name of the default DB
       */
      public String getDefaultDB()
      {
          if (conf == null)
          {
              return DEFAULT_NAME;
          }
          else if (defaultDBName == null)
          {
              // Determine default database name.
              defaultDBName =
                      conf.getString(Torque.DATABASE_DEFAULT, 
                              DEFAULT_NAME).trim();
          }
  
          return defaultDBName;
      }
  
      /**
       * Closes a connection.
       *
       * @param con A Connection to close.
       */
      public void closeConnection(Connection con)
      {
          if (con != null)
          {
              try
              {
                  con.close();
              }
              catch (SQLException e)
              {
                  log.error("Error occured while closing connection.", e);
              }
          }
      }
  }