/*
 * JBoss, Home of Professional Open Source
 * Copyright 2006, Red Hat Middleware LLC, and individual contributors 
 * as indicated by the @author tags. 
 * See the copyright.txt in the distribution for a
 * full listing of individual contributors. 
 * This copyrighted material is made available to anyone wishing to use,
 * modify, copy, or redistribute it subject to the terms and conditions
 * of the GNU Lesser General Public License, v. 2.1.
 * This program is distributed in the hope that it will be useful, but WITHOUT A 
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A 
 * PARTICULAR PURPOSE.  See the GNU Lesser General Public License for more details.
 * You should have received a copy of the GNU Lesser General Public License,
 * v.2.1 along with this distribution; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, 
 * MA  02110-1301, USA.
 * 
 * (C) 2005-2006,
 * @author JBoss Inc.
 */
/*
 * Copyright (C) 2000, 2001,
 *
 * Arjuna Solutions Limited,
 * Newcastle upon Tyne,
 * Tyne and Wear,
 * UK.  
 *
 * $Id: JDBCStore.java 2342 2006-03-30 13:06:17Z  $
 */

package com.arjuna.ats.internal.arjuna.objectstore;

import com.arjuna.ats.internal.arjuna.objectstore.JDBCImple;

import com.arjuna.ats.arjuna.ArjunaNames;
import com.arjuna.ats.arjuna.state.*;

import com.arjuna.ats.arjuna.logging.tsLogger;
import com.arjuna.ats.arjuna.logging.FacilityCode;

import com.arjuna.ats.arjuna.objectstore.ObjectStore;
import com.arjuna.ats.arjuna.objectstore.ObjectStoreImple;
import com.arjuna.ats.arjuna.objectstore.ObjectStoreType;
import com.arjuna.ats.arjuna.objectstore.jdbc.JDBCAccess;
import com.arjuna.ats.arjuna.common.*;
import com.arjuna.ats.arjuna.gandiva.ObjectName;
import com.arjuna.ats.arjuna.gandiva.ClassName;

import com.arjuna.common.util.logging.DebugLevel;
import com.arjuna.common.util.logging.VisibilityLevel;

import java.sql.*;
import java.util.HashMap;

import com.arjuna.ats.arjuna.exceptions.ObjectStoreException;
import com.arjuna.ats.arjuna.exceptions.ObjectStoreError;
import com.arjuna.ats.arjuna.exceptions.FatalError;

import java.io.IOException;

/**
 * An object store implementation which uses a JDBC database for maintaining
 * object states. All states are maintained within a single table.
 * 
 * It is assumed that only one object will use a given instance of the
 * JDBCStore. Hence, there is no need for synchronizations.
 * 
 * @message com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_1
 *          [com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_1] - JDBCStore
 *          could not setup store < {0} , {1} >
 * @message com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_2
 *          [com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_2] - Received:
 *          {0} for: {1}
 * @message com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_3
 *          [com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_3] -
 *          JDBCStore.setupStore failed to initialise!
 * @message com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_4
 *          [com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_4] - JDBCStore
 *          invalid ObjectName parameter: {0}
 * @message com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_5
 *          [com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_5] - No
 *          JDBCAccess implementation provided!
 */

public class JDBCStore extends ObjectStoreImple
{

	public String getStoreName()
	{
		if (storeValid())
			return getAccessClassName() + ":" + getTableName();
		else
			return "Invalid";
	}

	public int typeIs()
	{
		return ObjectStoreType.JDBC;
	}

	public boolean commit_state(Uid objUid, String tName)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"JDBCStore.commit_state(" + objUid + ", " + tName + ")");
		}

		/* Bail out if the object store is not set up */

		if (!storeValid())
			return false;
		else
			return _theImple.commit_state(objUid, tName, getTableName());
	}

	public boolean hide_state(Uid objUid, String tName)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"ShadowingStore.hide_state(" + objUid + ", " + tName + ")");
		}

		/* Bail out if the object store is not set up */

		if (storeValid())
			return _theImple.hide_state(objUid, tName, getTableName());
		else
			return false;
	}

	public boolean reveal_state(Uid objUid, String tName)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"ShadowingStore.reveal_state(" + objUid + ", " + tName
							+ ")");
		}

		if (storeValid())
			return _theImple.reveal_state(objUid, tName, getTableName());
		else
			return false;
	}

	/*
	 * Determine current state of object. State search is ordered
	 * OS_UNCOMMITTED, OS_UNCOMMITTED_HIDDEN, OS_COMMITTED, OS_COMMITTED_HIDDEN
	 */

	public int currentState(Uid objUid, String tName)
			throws ObjectStoreException
	{
		if (storeValid())
			return _theImple.currentState(objUid, tName, getTableName());
		else
			return ObjectStore.OS_UNKNOWN;
	}

	/**
	 * Read an uncommitted instance of State out of the object store. The
	 * instance is identified by the unique id and type
	 */

	public InputObjectState read_committed(Uid storeUid, String tName)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger
					.debug(DebugLevel.FUNCTIONS, VisibilityLevel.VIS_PUBLIC,
							FacilityCode.FAC_OBJECT_STORE,
							"JDBCStore.read_committed(" + storeUid + ", "
									+ tName + ")");
		}

		return read_state(storeUid, tName, ObjectStore.OS_COMMITTED);
	}

	public InputObjectState read_uncommitted(Uid storeUid, String tName)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"JDBCStore.read_uncommitted(" + storeUid + ", " + tName
							+ ")");
		}

		return read_state(storeUid, tName, ObjectStore.OS_UNCOMMITTED);
	}

	public boolean remove_committed(Uid storeUid, String tName)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"JDBCStore.remove_committed(" + storeUid + ", " + tName
							+ ")");
		}

		return remove_state(storeUid, tName, ObjectStore.OS_COMMITTED);
	}

	public boolean remove_uncommitted(Uid storeUid, String tName)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"JDBCStore.remove_uncommitted(" + storeUid + ", " + tName
							+ ")");
		}

		return remove_state(storeUid, tName, ObjectStore.OS_UNCOMMITTED);
	}

	public boolean write_committed(Uid storeUid, String tName,
			OutputObjectState state) throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"JDBCStore.write_committed(" + storeUid + ", " + tName
							+ ")");
		}

		return write_state(storeUid, tName, state, ObjectStore.OS_COMMITTED);
	}

	public boolean write_uncommitted(Uid storeUid, String tName,
			OutputObjectState state) throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"JDBCStore.write_uncommitted(" + storeUid + ", " + tName
							+ ", " + state + ")");
		}

		return write_state(storeUid, tName, state, ObjectStore.OS_UNCOMMITTED);
	}

	public final boolean storeValid()
	{
		return _isValid;
	}

	/*
	 * Given a type name return an ObjectState that contains all of the uids of
	 * objects of that type
	 */

	public boolean allObjUids(String tName, InputObjectState state, int match)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"JDBCStore.allObjUids(" + tName + ", " + state + ", "
							+ match + ")");
		}

		if (storeValid())
			return _theImple.allObjUids(tName, state, match, getTableName());
		else
			return false;
	}

	public boolean allTypes(InputObjectState foundTypes)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					"JDBCStore.allTypes(" + foundTypes + ")");
		}

		if (storeValid())
			return _theImple.allTypes(foundTypes, getTableName());
		else
			return false;
	}

	public synchronized void packInto(OutputBuffer buff) throws IOException
	{
		buff.packString(getAccessClassName());
		buff.packString(getTableName());
	}

	public synchronized void unpackFrom(InputBuffer buff) throws IOException
	{
		setAccessClassName(buff.unpackString());
		setTableName(buff.unpackString());
	}

	public ClassName className()
	{
		return ArjunaNames.Implementation_ObjectStore_JDBCStore();
	}

	public static ClassName name()
	{
		return ArjunaNames.Implementation_ObjectStore_JDBCStore();
	}

	protected InputObjectState read_state(Uid objUid, String tName, int ft)
			throws ObjectStoreException
	{
		if (!storeValid())
			return null;
		else
			return _theImple.read_state(objUid, tName, ft, getTableName());
	}

	/**
	 * We don't actually delete the state entry, only change its type.
	 */

	protected boolean remove_state(Uid objUid, String name, int ft)
			throws ObjectStoreException
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.FUNCTIONS,
					VisibilityLevel.VIS_PROTECTED,
					FacilityCode.FAC_OBJECT_STORE, "JDBCStore.remove_state("
							+ objUid + ", " + name + ", "
							+ ObjectStore.stateTypeString(ft) + ")");
		}

		if (!storeValid())
			return false;
		else
			return _theImple.remove_state(objUid, name, ft, getTableName());
	}

	protected boolean write_state(Uid objUid, String tName,
			OutputObjectState state, int s) throws ObjectStoreException
	{
		if (!storeValid())
			return false;
		else
			return _theImple.write_state(objUid, tName, state, s,
					getTableName());
	}

	public static JDBCStore create()
	{
		return new JDBCStore();
	}

	public static JDBCStore create(Object[] param)
	{
		if (param == null)
			return null;

		return new JDBCStore((String) param[0]); /*
													 * param[0] should be the
													 * table name
													 */
	}

	public static JDBCStore create(ObjectName param)
	{
		if (param == null)
			return null;

		return new JDBCStore(param);
	}

	protected JDBCStore()
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.CONSTRUCTORS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					getClass().getName() + "()");
		}

		try
		{
			initialise("");
		}
		catch (Exception e)
		{
			throw new ObjectStoreError();
		}
	}

	protected JDBCStore(String tableName)
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.CONSTRUCTORS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					getClass().getName() + "(" + tableName + ")");
		}

		try
		{
			initialise(tableName);
		}
		catch (Exception e)
		{
			throw new ObjectStoreError();
		}
	}

	protected JDBCStore(ObjectName objName)
	{
		if (tsLogger.arjLogger.debugAllowed())
		{
			tsLogger.arjLogger.debug(DebugLevel.CONSTRUCTORS,
					VisibilityLevel.VIS_PUBLIC, FacilityCode.FAC_OBJECT_STORE,
					getClass().getName() + "(" + objName + " )");
		}

		try
		{
			parseObjectName(objName);
		}
		catch (Exception e)
		{
			throw new ObjectStoreError();
		}
	}

	/**
	 * Get the JDBC access class name.
	 * 
	 * @return The access class name.
	 */
	protected String getAccessClassName()
	{
		if (_jdbcAccessClassName == null)
			_jdbcAccessClassName = arjPropertyManager.propertyManager
					.getProperty(Environment.JDBC_USER_DB_ACCESS);
		return _jdbcAccessClassName;
	}

	/**
	 * Set the JDBC access class name.
	 * 
	 * @param The
	 *            access class name.
	 */
	protected void setAccessClassName(String jdbcAccessClassName)
	{
		_jdbcAccessClassName = jdbcAccessClassName;
	}

	/**
	 * Get the JDBC default table name.
	 * 
	 * @return The default table name.
	 */
	protected String getDefaultTableName()
	{
		return _defaultTableName;
	}

	/**
	 * Get the JDBC access class name from an object.
	 * 
	 * @param The
	 *            object name.
	 * @return The access class name.
	 */
	protected String getAccessClassNameFromObject(ObjectName objName)
			throws IOException
	{
		return objName.getStringAttribute(Environment.JDBC_USER_DB_ACCESS);
	}

	/**
	 * Get the JDBC table name from an object.
	 * 
	 * @param The
	 *            object name.
	 * @return The table name.
	 */
	protected String getTableNameFromObject(ObjectName objName)
			throws IOException
	{
		return objName.getStringAttribute(ArjunaNames
				.Implementation_ObjectStore_JDBC_tableName());
	}

	/**
	 * Get the JDBC access class.
	 * 
	 * @return The jdbc access variable.
	 */
	protected JDBCAccess getJDBCAccess()
	{
		return _jdbcAccess;
	}

	/**
	 * Set the JDBC access class.
	 * 
	 * @param jdbcAccess
	 *            The jdbc access variable.
	 */
	protected void setJDBCAccess(JDBCAccess jdbcAccess)
	{
		_jdbcAccess = jdbcAccess;
	}

	/**
	 * Get the JDBC table name.
	 * 
	 * @return The table name.
	 */
	protected String getTableName()
	{
		return _jdbcTableName;
	}

	/**
	 * Set the JDBC table name.
	 * 
	 * @param tableName
	 *            The table name.
	 */
	protected void setTableName(String tableName)
	{
		_jdbcTableName = tableName;
	}

	protected void initialise(String tableName) throws Exception
	{
		String jdbcAccessClassName = getAccessClassName();

		if (jdbcAccessClassName == null)
		{
			if (tsLogger.arjLoggerI18N.isFatalEnabled())
				tsLogger.arjLoggerI18N
						.fatal("com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_5");

			throw new FatalError(
					tsLogger.log_mesg
							.getString("com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_5"));
		}

		try
		{
			setupStore(jdbcAccessClassName, tableName);
		}
		catch (Exception e)
		{
			if (tsLogger.arjLoggerI18N.isFatalEnabled())
			{
				tsLogger.arjLoggerI18N
						.fatal(
								"com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_1",
								new Object[]
								{ getJDBCAccess(), getTableName() });
			}
			throw e;
		}

		_isValid = true;
	}

	protected void parseObjectName(ObjectName objName) throws Exception
	{
		String jdbcAccessClassName, tableName;
		JDBCAccess jdbcAccess;

		if (objName == null)
		{
			if (tsLogger.arjLoggerI18N.isFatalEnabled())
			{
				tsLogger.arjLoggerI18N
						.fatal(
								"com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_4",
								new Object[]
								{ "null" });
			}
			throw new Exception();
		}

		try
		{
			jdbcAccessClassName = getAccessClassNameFromObject(objName);
			tableName = getTableNameFromObject(objName);
		}
		catch (Exception e)
		{
			if (tsLogger.arjLoggerI18N.isFatalEnabled())
			{
				tsLogger.arjLoggerI18N
						.fatal(
								"com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_4",
								new Object[]
								{ objName });
			}
			throw e;
		}

		try
		{
			setupStore(jdbcAccessClassName, tableName);
		}
		catch (Exception e)
		{
			if (tsLogger.arjLoggerI18N.isFatalEnabled())
			{
				tsLogger.arjLoggerI18N
						.fatal(
								"com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_1",
								new Object[]
								{ getJDBCAccess(), getTableName() });
			}
			throw e;
		}

		_isValid = true;
	}

	/*
	 * Try to create the original and shadow/hidden tables. If this fails, then
	 * we will exit.
	 */
	protected void setupStore(String jdbcAccessClassName, String tableName)
			throws Exception
	{
		if (jdbcAccessClassName == null || jdbcAccessClassName.length() == 0)
			throw new ObjectStoreException();

		final JDBCAccess jdbcAccess;
		synchronized (_theAccesses)
		{
			final Object jdbcAccessObject = _theAccesses
					.get(jdbcAccessClassName);
			if (jdbcAccessObject != null)
			{
				jdbcAccess = (JDBCAccess) jdbcAccessObject;
			}
			else
			{
				try
				{
					final Class jdbcAccessClass = Thread.currentThread()
							.getContextClassLoader().loadClass(
									jdbcAccessClassName);
					jdbcAccess = (JDBCAccess) jdbcAccessClass.newInstance();
				}
				catch (final Exception ex)
				{
					if (tsLogger.arjLoggerI18N.isFatalEnabled())
					{
						tsLogger.arjLoggerI18N
								.fatal(
										"com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_2",
										new Object[]
										{ ex, jdbcAccessClassName });
					}
					throw ex;
				}
				_theAccesses.put(jdbcAccessClassName, jdbcAccess);
			}
		}
		setJDBCAccess(jdbcAccess);

		final String impleTableName;
		if ((tableName != null) && (tableName.length() > 0))
		{
			impleTableName = tableName;
		}
		else
		{
			final String jdbcAccessTableName = jdbcAccess.tableName();
			if ((jdbcAccessTableName != null)
					&& (jdbcAccessTableName.length() > 0))
			{
				impleTableName = jdbcAccessTableName;
			}
			else
			{
				impleTableName = getDefaultTableName();
			}
		}

		setTableName(impleTableName);

		final String impleKey = jdbcAccessClassName + ":" + impleTableName;

		synchronized (_theImples)
		{
			final Object currentImple = _theImples.get(impleKey);
			if (currentImple != null)
			{
				_theImple = (JDBCImple) currentImple;
			}
			else
			{
				try
				{
					/*
					 * This had better not be an Arjuna jdbc connection!
					 */
					final Connection connection;

					try
					{
						connection = jdbcAccess.getConnection();
					}
					catch (final SQLException sqle)
					{
						if (tsLogger.arjLoggerI18N.isFatalEnabled())
						{
							tsLogger.arjLoggerI18N
									.fatal(
											"com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_2",
											new Object[]
											{ sqle, "getConnection()" });
						}
						throw sqle;
					}

					if (connection == null)
					{
						if (tsLogger.arjLoggerI18N.isFatalEnabled())
						{
							tsLogger.arjLoggerI18N
									.fatal(
											"com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_1",
											new Object[]
											{ getJDBCAccess(), getTableName() });
						}
						throw new SQLException("getConnection returned null");
					}
					boolean success = false;
					try
					{
						connection.setAutoCommit(true);
						final JDBCImple jdbcImple;
						try
						{
							final Class jdbcImpleClass = getJDBCClass(connection);
							jdbcImple = (JDBCImple) jdbcImpleClass
									.newInstance();
							jdbcImple.setShareStatus(shareStatus);
						}
						catch (final Exception ex)
						{
							if (tsLogger.arjLoggerI18N.isFatalEnabled())
							{
								tsLogger.arjLoggerI18N
										.fatal(
												"com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_2",
												new Object[]
												{ ex, getJDBCAccess() });
							}
							throw ex;
						}

						if (!jdbcImple.initialise(connection, jdbcAccess,
								impleTableName))
						{
							if (tsLogger.arjLoggerI18N.isWarnEnabled())
								tsLogger.arjLoggerI18N
										.warn("com.arjuna.ats.internal.arjuna.objectstore.JDBCStore_3");
							throw new ObjectStoreException();
						}
						else
						{
							_theImples.put(impleKey, jdbcImple);
							_theImple = jdbcImple;
							success = true;
						}
					}
					finally
					{
						if (!success)
						{
							try
							{
								connection.close();
							}
							catch (final SQLException sqle)
							{
							} // Ignore exception
						}
					}
				}
				catch (Exception e)
				{
					tsLogger.arjLogger.warn(e.toString());
					throw e;
				}
			}
			_isValid = true;
		}
	}

	/**
	 * Attempt to load the database class. &nbsp;This method searches for a
	 * class called <name>_<major>_<minor>, then <name>_<major> and finally
	 * <dbName>
	 * 
	 * @param conn
	 *            A database connection.
	 * @return The database class.
	 * @throws ClassNotFoundException
	 *             If no database class can be found.
	 * @throws SQLException
	 *             If the database connection cannot be interrogated.
	 */
	protected Class getJDBCClass(Connection conn)
			throws ClassNotFoundException, SQLException
	{
		DatabaseMetaData md = conn.getMetaData();

		String name = md.getDriverName();
		int major = md.getDriverMajorVersion();
		int minor = md.getDriverMinorVersion();

		/*
		 * Check for spaces in the name - our implementation classes are always
		 * just the first part of such names.
		 */

		int index = name.indexOf(' ');

		if (index != -1)
			name = name.substring(0, index);

		name = name.toLowerCase();

		final ClassLoader classLoader = Thread.currentThread()
				.getContextClassLoader();
		final String packageName = getClass().getPackage().getName() + ".jdbc.";
		try
		{
			return classLoader.loadClass(packageName + name + "_" + major + "_"
					+ minor + "_driver");
		}
		catch (final ClassNotFoundException cnfe)
		{
		}
		try
		{
			return classLoader.loadClass(packageName + name + "_" + major
					+ "_driver");
		}
		catch (final ClassNotFoundException cnfe)
		{
		}
		return classLoader.loadClass(packageName + name + "_driver");
	}

	protected boolean supressEntry(String name)
	{
		return true;
	}

	/*
	 * Instance specific data.
	 */

	protected boolean _isValid;

	protected JDBCImple _theImple;

	private JDBCAccess _jdbcAccess;

	private String _jdbcAccessClassName;

	private String _jdbcTableName;

	private static String _defaultTableName = "JBossTSTable";

	/*
	 * Class data.
	 */

	protected static final HashMap _theImples = new HashMap();

	protected static final HashMap _theAccesses = new HashMap();
}
