/* * 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.jdbc; import java.io.IOException; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.util.HashMap; import java.util.Map; import java.util.StringTokenizer; import com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean; import com.arjuna.ats.arjuna.common.Uid; import com.arjuna.ats.arjuna.exceptions.ObjectStoreException; import com.arjuna.ats.arjuna.logging.tsLogger; import com.arjuna.ats.arjuna.objectstore.ObjectStoreAPI; import com.arjuna.ats.arjuna.objectstore.StateStatus; import com.arjuna.ats.arjuna.objectstore.jdbc.JDBCAccess; import com.arjuna.ats.arjuna.state.InputBuffer; import com.arjuna.ats.arjuna.state.InputObjectState; import com.arjuna.ats.arjuna.state.OutputBuffer; import com.arjuna.ats.arjuna.state.OutputObjectState; /** * 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. */ public class JDBCStore implements ObjectStoreAPI { protected JDBCImple_driver _theImple; private static final String DEFAULT_TABLE_NAME = "JBossTSTxTable"; protected String tableName; protected final ObjectStoreEnvironmentBean jdbcStoreEnvironmentBean; private String _storeName; private static Map<String, JDBCImple_driver> imples = new HashMap<String, JDBCImple_driver>(); private static Map<String, String> storeNames = new HashMap<String, String>(); @Override public void start() { } @Override public void stop() { } /** * Does this store need to do the full write_uncommitted/commit protocol? * * @return <code>true</code> if full commit is needed, <code>false</code> * otherwise. */ public boolean fullCommitNeeded() { return true; } /** * Some object store implementations may be running with automatic sync * disabled. Calling this method will ensure that any states are flushed to * disk. */ public void sync() throws java.io.SyncFailedException, ObjectStoreException { } /** * Is the current state of the object the same as that provided as the last * parameter? * * @param u * The object to work on. * @param tn * The type of the object. * @param st * The expected type of the object. * * @return <code>true</code> if the current state is as expected, * <code>false</code> otherwise. */ public boolean isType(Uid u, String tn, int st) throws ObjectStoreException { return (currentState(u, tn) == st); } public String getStoreName() { return _storeName; } public boolean allObjUids(String s, InputObjectState buff) throws ObjectStoreException { return allObjUids(s, buff, StateStatus.OS_UNKNOWN); } public boolean commit_state(Uid objUid, String tName) throws ObjectStoreException { return _theImple.commit_state(objUid, tName); } public boolean hide_state(Uid objUid, String tName) throws ObjectStoreException { return _theImple.hide_state(objUid, tName); } public boolean reveal_state(Uid objUid, String tName) throws ObjectStoreException { return _theImple.reveal_state(objUid, tName); } public int currentState(Uid objUid, String tName) throws ObjectStoreException { return _theImple.currentState(objUid, tName); } public InputObjectState read_committed(Uid storeUid, String tName) throws ObjectStoreException { return _theImple.read_state(storeUid, tName, StateStatus.OS_COMMITTED); } public InputObjectState read_uncommitted(Uid storeUid, String tName) throws ObjectStoreException { return _theImple.read_state(storeUid, tName, StateStatus.OS_UNCOMMITTED); } public boolean remove_committed(Uid storeUid, String tName) throws ObjectStoreException { return _theImple.remove_state(storeUid, tName, StateStatus.OS_COMMITTED); } public boolean remove_uncommitted(Uid storeUid, String tName) throws ObjectStoreException { return _theImple.remove_state(storeUid, tName, StateStatus.OS_UNCOMMITTED); } public boolean write_committed(Uid storeUid, String tName, OutputObjectState state) throws ObjectStoreException { return _theImple.write_state(storeUid, tName, state, StateStatus.OS_COMMITTED); } public boolean write_uncommitted(Uid storeUid, String tName, OutputObjectState state) throws ObjectStoreException { return _theImple.write_state(storeUid, tName, state, StateStatus.OS_UNCOMMITTED); } public boolean allObjUids(String tName, InputObjectState state, int match) throws ObjectStoreException { return _theImple.allObjUids(tName, state, match); } public boolean allTypes(InputObjectState foundTypes) throws ObjectStoreException { return _theImple.allTypes(foundTypes); } public synchronized void packInto(OutputBuffer buff) throws IOException { buff.packString(tableName); } public synchronized void unpackFrom(InputBuffer buff) throws IOException { this.tableName = buff.unpackString(); } /** * Create a new JDBCStore * * @param jdbcStoreEnvironmentBean * The environment bean containing the configuration * @throws ObjectStoreException * In case the store environment bean was not correctly * configured */ public JDBCStore(ObjectStoreEnvironmentBean jdbcStoreEnvironmentBean) throws ObjectStoreException { this.jdbcStoreEnvironmentBean = jdbcStoreEnvironmentBean; String connectionDetails = jdbcStoreEnvironmentBean.getJdbcAccess(); String key; if (connectionDetails == null) { throw new ObjectStoreException(tsLogger.i18NLogger.get_objectstore_JDBCStore_5()); } String impleTableName = DEFAULT_TABLE_NAME; final String tablePrefix = jdbcStoreEnvironmentBean.getTablePrefix(); if ((tablePrefix != null) && (tablePrefix.length() > 0)) { impleTableName = tablePrefix + impleTableName; } tableName = impleTableName; key = connectionDetails + tableName; _theImple = imples.get(key); _storeName = storeNames.get(key); if (_theImple == null) { try { StringTokenizer stringTokenizer = new StringTokenizer(connectionDetails, ";"); JDBCAccess jdbcAccess = (JDBCAccess) Class.forName(stringTokenizer.nextToken()).newInstance(); jdbcAccess.initialise(stringTokenizer); _storeName = jdbcAccess.getClass().getName() + ":" + tableName; Connection connection = jdbcAccess.getConnection(); String name; int major; int minor; try { DatabaseMetaData md = connection.getMetaData(); name = md.getDriverName(); major = md.getDriverMajorVersion(); minor = md.getDriverMinorVersion(); } finally { connection.close(); } /* * 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.replaceAll("-", "_"); name = name.toLowerCase(); final String packagePrefix = JDBCStore.class.getName().substring(0, JDBCStore.class.getName().lastIndexOf('.')) + ".drivers."; Class jdbcImpleClass = null; try { jdbcImpleClass = Class.forName(packagePrefix + name + "_" + major + "_" + minor + "_driver"); } catch (final ClassNotFoundException cnfe) { try { jdbcImpleClass = Class.forName(packagePrefix + name + "_" + major + "_driver"); } catch (final ClassNotFoundException cnfe2) { jdbcImpleClass = Class.forName(packagePrefix + name + "_driver"); } } _theImple = (com.arjuna.ats.internal.arjuna.objectstore.jdbc.JDBCImple_driver) jdbcImpleClass.newInstance(); _theImple.initialise(jdbcAccess, tableName, jdbcStoreEnvironmentBean); imples.put(key, _theImple); storeNames.put(key, _storeName); } catch (Exception e) { tsLogger.i18NLogger.fatal_objectstore_JDBCStore_2(_storeName, e); throw new ObjectStoreException(e); } } } }