package com.sptci.jdo;

import java.io.FileInputStream;
import java.util.Properties;
import java.util.logging.Logger;

import javax.jdo.JDOHelper;
import javax.jdo.PersistenceManager;

import com.sptci.util.StringUtilities;

/**
 * A factory for accessing instances of a <code>JDO Persistence
 * Manager</code> that are necessary for interacting with the
 * <code>JDO data store</code>.
 *
 * @author Rakesh Vidyadharan 05<sup><small>th</small></sup> February, 2006
 * <p>Copyright 2006, Sans Pareil Technologies, Inc.</p>
 *
 * @version $Id: PersistenceManagerFactory.java,v 1.2 2006/02/14 22:41:41 rakesh Exp $
 */
public final class PersistenceManagerFactory extends Object
{
  /**
   * The logger used to log messages to.
   */
  private static final Logger logger =
    Logger.getLogger( "com.sptci.jdo.PersistenceManagerFactory" );

  /**
   * The name of the system property used to specify the location of
   * the JDO DataStore connection properties.
   */
  private static final String JDO_DATASTORE_PROPERTIES = "JDODataStoreProperties";

  /**
   * The single application wide instanace that is used to manage
   * read only objects.
   */
  private static PersistenceManager persistenceManager;

  /**
   * Initialise the {@link #persistenceManager}
   */
  static
  {
    try
    {
      initPersistenceManager();
    }
    catch ( Throwable t )
    {
      logger.severe( 
          "Error initialising PersistenceManager.\n" +
          StringUtilities.stackTrace( t ) );
    }
  }

  /**
   * Default constructor.  Cannot be initialsed.
   */
  private PersistenceManagerFactory() {}

  /**
   * Return an instance of a <code>PersistenceManager</code> for
   * interacting with the <code>JDO data store</code>.
   *
   * @see #initPersistenceManager
   * @throws RuntimeException If errors are encountered while reading
   *   the properties file
   */
  public static final javax.jdo.PersistenceManager getPersistenceManager()
    throws RuntimeException
  {
    if ( persistenceManager.isClosed() )
    {
      initPersistenceManager();
    }

    return persistenceManager;
  }

  /**
   * Initialise the {@link #persistenceManager} if it has not already
   * been initialised, or has been closed.
   *
   * @see #fetchProperties
   * @throws RuntimeException If errors are encountered while reading
   *   the properties file while initialising the persistence
   *   manager.
   */
  private synchronized static final void initPersistenceManager()
    throws RuntimeException
  {
    logger.info( 
        "Initialising persistence manager" );
    PersistenceManager pm = JDOHelper.getPersistenceManagerFactory( 
          fetchProperties() ).getPersistenceManager();
    persistenceManager = pm;
  }

  /**
   * Open the properties file and read the properties from it.
   * The full path to the properties file must be specified as a
   * system property with name <code>ObjectDBProperties</code>
   *
   * @see #JDO_DATASTORE_PROPERTIES
   * @return Properties - The initialised properties object.
   * @throws RuntimeException If errors are encountered while reading
   *   the properties file
   */
  private static final Properties fetchProperties() throws RuntimeException
  {
    Properties properties = new Properties();

    try
    {
      FileInputStream fis = new FileInputStream( 
          System.getProperties().getProperty( JDO_DATASTORE_PROPERTIES ) );
      properties.load( fis );
      fis.close();
    }
    catch ( Throwable t )
    { 
      throw new RuntimeException( t.getMessage(), t );
    } 

    return properties;
  }   
}
