[jboss-svn-commits] JBL Code SVN: r37834 - in labs/jbosstm/trunk/qa/tests/product/src: com and 9 other directories.

jboss-svn-commits at lists.jboss.org jboss-svn-commits at lists.jboss.org
Thu Jan 5 02:28:03 EST 2012


Author: tomjenkinson
Date: 2012-01-05 02:28:03 -0500 (Thu, 05 Jan 2012)
New Revision: 37834

Added:
   labs/jbosstm/trunk/qa/tests/product/src/com/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/JDBCAccess.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/h2_driver.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/DbWrapper.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/PerfTest.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/TestRunner.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/AtomikosProduct.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/BitronixProduct.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/JBossTSProduct.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/JOTMProduct.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/NonXAProduct.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/Product.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/SimpleJTAProduct.java
   labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/XAProduct.java
Log:
Taken the perfest and objectstore test from branch

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/JDBCAccess.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/JDBCAccess.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/JDBCAccess.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,77 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2007, 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) 2004
+ *
+ * Arjuna Technologies Ltd.,
+ * Newcastle upon Tyne,
+ * UK.
+ *
+ * $Id: JDBCAccess.java,v 1.2 2004/10/07 15:42:44 jcoleman Exp $
+ *
+ * Provide JDBC connections for JDBC object store and action store.
+ * Uses profiles stored in JDBCProfiles and selected using property
+ * "org.jboss.jbossts.qa.JDBCAccess".
+ */
+
+package com.arjuna.ats.internal.arjuna.objectstore.jdbc;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+
+public class JDBCAccess implements com.arjuna.ats.arjuna.objectstore.jdbc.JDBCAccess
+{
+	private static final String dbProp = "org.jboss.jbossts.qa.Utils.JDBCAccess";
+
+	public Connection getConnection() throws SQLException
+	{
+        try
+        {   //CHECKPOINT SYNC
+            Class.forName("org.h2.Driver");
+            return DriverManager.getConnection("jdbc:h2:~/os;WRITE_DELAY=0", "sa", "");
+        }
+        catch (ClassNotFoundException e)
+        {
+            e.printStackTrace();
+            return null;
+        }
+    }
+
+	public void putConnection(Connection conn)
+	{
+	}
+
+	public String tableName()
+	{
+		return "";
+	}
+
+	public boolean dropTable()
+	{
+		return false;
+	}
+
+	public void initialise(ObjectName objName)
+	{
+	}
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/h2_driver.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/h2_driver.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/internal/arjuna/objectstore/jdbc/h2_driver.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,5 @@
+package com.arjuna.ats.internal.arjuna.objectstore.jdbc;
+
+public class h2_driver extends apache_driver
+{
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/DbWrapper.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/DbWrapper.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/DbWrapper.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,496 @@
+package com.arjuna.ats.tools.perftest;
+
+import com.arjuna.ats.jta.xa.XidImple;
+import com.arjuna.ats.arjuna.common.Uid;
+import com.arjuna.ats.tools.perftest.product.Product;
+
+import javax.sql.DataSource;
+import javax.sql.XADataSource;
+import javax.transaction.xa.Xid;
+import javax.naming.NamingException;
+import java.util.Properties;
+import java.util.Hashtable;
+import java.sql.SQLException;
+import java.sql.DriverManager;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.io.File;
+
+import org.apache.log4j.Logger;
+
+public class DbWrapper
+{
+    private final static Logger log = Logger.getLogger(Product.class);
+    private static final String JNDIBASE = "jndi/";
+
+    public static DataSource initMysqlDS(XADataSource xds, String user, String pass, String url)
+    {
+        log.fatal("Mysql support is disabled - please uncomment the implementation of " + DbWrapper.class.getCanonicalName() + ".initMysqlDS");
+
+        return null;
+/*
+        com.mysql.jdbc.jdbc2.optional.MysqlXADataSource ds = (com.mysql.jdbc.jdbc2.optional.MysqlXADataSource) xds;
+        ds.setUser(user);
+        ds.setPassword(pass);
+        ds.setURL(url);
+
+        return ds;
+*/
+    }
+
+    public static DataSource initDerbyDS(String dsName, final Properties props, String host, String user, String pass)
+    {
+        log.fatal("Derby support is disabled - please uncomment the implementation of " + DbWrapper.class.getCanonicalName() + ".initDerbyDS");
+        return null;
+/*
+        String dbName = getDbName(props);
+        Integer port = getDbPort(props);
+
+        if (host != null)
+        {
+            org.apache.derby.jdbc.ClientXADataSource cds = new org.apache.derby.jdbc.ClientXADataSource();
+
+            cds.setServerName (host);
+            cds.setDatabaseName(dbName);
+            if (port != null)
+                cds.setPortNumber(port);
+            cds.setUser(user);
+            cds.setPassword(pass);
+            cds.setDataSourceName(dsName);
+            cds.setConnectionAttributes((String) props.get("connectionAttributes"));
+            if (props.get("traceLevel") != null)
+            {
+                cds.setTraceFile((String) props.get("debug.file"));
+                cds.setTraceLevel(Integer.parseInt((String) props.get("debug.level")));
+            }
+            return cds;
+        }
+        else
+        {
+            org.apache.derby.jdbc.EmbeddedXADataSource eds = new org.apache.derby.jdbc.EmbeddedXADataSource();
+
+            eds.setDatabaseName(dbName);
+            eds.setUser(user);
+            eds.setPassword(pass);
+            eds.setDataSourceName(dsName);
+//                eds.setConnectionAttributes((String) props.get("connectionAttributes"));
+            eds.setConnectionAttributes((String) props.get("db.opts"));
+
+            return eds;
+        }
+*/
+    }
+
+    public static DataSource createDataSource(String dsName, final Properties props) throws SQLException
+    {
+        String db = DbWrapper.getDbType(props);
+        String url = DbWrapper.getDbUrl(props);
+        String user = DbWrapper.getDbUser(props);
+        String pass = DbWrapper.getDbPassword(props);
+        String host = getDbHost(props);
+        boolean embedded = host == null;
+
+        if (isMysql(db))
+        {
+            XADataSource xds = createDataSource(getDbXADsClass(db, embedded));
+
+            return initMysqlDS(xds, user, pass, url);
+        }
+        else if (isH2(db))
+        {
+            org.h2.jdbcx.JdbcDataSource ds = new org.h2.jdbcx.JdbcDataSource();
+
+            ds.setUser(user);
+            ds.setPassword(pass);
+
+            int i = url.indexOf(';');
+
+            if (i != -1)
+                url = url.substring(0, i);
+
+            ds.setURL(url);
+
+            return ds;
+        }
+        else if (isDerby(db))
+        {
+            return initDerbyDS(dsName, props, host, user, pass);
+        }
+        else
+        {
+            return null;
+        }
+    }
+
+    public static java.sql.Connection getConnection(String url) throws SQLException
+    {
+        Properties props = new Properties();
+
+        parseUrl(url, props);
+
+        DataSource ds = createDataSource("", props);
+
+        return ds.getConnection();
+    }
+
+    public static Properties getDbProperties(Properties props)
+    {
+        Properties p = new Properties();
+        String type = getDbType(props);
+        String name = getDbName(props);
+
+        if (isDerby(type))
+        {
+            // NB derby.system.durability=test disables I/O synchronization
+            p.put("databaseName", name);
+            p.put("createDatabase", "true");
+            p.put("shutdownDatabase", "false");
+            p.put("dataSourceName", name);
+//            p.put("description", name);
+//            String opts = getDbOpts(p);
+//            if (opts != null)
+//                p.put("connectionAttributes", opts.replace('&', ';'));
+        }
+        else if (isH2(type))
+        {
+            p.put("user", getDbUser(props));
+            p.put("password", getDbPassword(props));
+            p.put("URL", getDbUrl(props));
+        }
+        else if (isMysql(type))
+        {
+            p.put("user", getDbUser(props));
+            p.put("password", getDbPassword(props));
+        }
+
+        return p;
+    }
+
+    /*
+     * decode a jdbc connectin url
+
+    jdbc:h2:tcp://localhost/rc;user=user1;password=pass1
+    jdbc:h2:db2"
+    jdbc:derby:db1;create=true
+    jdbc:derby://localhost:1527/db1;create=true
+    jdbc:mysql://localhost:3306/db1?createDatabaseIfNotExist=true
+
+     */
+    private static final String[] URLS = {
+            "jdbc:h2:tcp:",
+            "jdbc:h2:",
+            "jdbc:derby:net:",
+            "jdbc:derby://",
+            "jdbc:derby:",
+            "jdbc:mysql:",
+            "jdbc:postgresql:",
+    };
+
+    public static void parseUrl(String url, Properties props)
+    {
+        props.put("db.url", url);
+
+        url = url.replace("jdbc:", "").replaceFirst(";", "?").replace(';', '&');
+
+        if (url.startsWith("h2:tcp:"))
+            url = url.replace(":tcp", "");
+
+        try
+        {
+            URI uri = new URI(url);
+
+            props.put("db.type", uri.getScheme());
+            if (uri.getHost() != null) props.put("db.host", uri.getHost());
+            if (uri.getPort() != -1) props.put("db.port", uri.getPort());
+            if (uri.getPath() != null)
+                props.put("db.name", uri.getPath().replace("/", ""));
+            else
+                props.put("db.name", parseDbName(uri.getSchemeSpecificPart()));
+            if (uri.getQuery() != null)
+                props.put("db.opts", uri.getQuery());
+            else if (url.indexOf('?') != -1 && url.indexOf('?') + 1 != url.length())
+                props.put("db.opts", url.substring(url.indexOf('?') + 1));
+            else
+                props.put("db.opts", "");
+
+            props.put("db.driver", getDbDriver(getDbType(props), getDbHost(props) == null));
+            props.put("db.xaclass", getDbXADsClass(getDbType(props), getDbHost(props) == null));
+
+            String opts = (String) props.get("db.opts");
+            for (String opt : opts.split("&"))
+            {
+                String[] nvl = opt.split("=");
+//                props.put(nvl[0], nvl[1]);
+                if ("user".equals(nvl[0]))
+                    props.put("db.user", nvl[1]);
+                if ("password".equals(nvl[0]))
+                    props.put("db.password", nvl[1]);
+            }
+
+            props.put("db.opts", opts);
+        }
+        catch (URISyntaxException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    private static String parseDbName(String s)
+    {   //jdbc:derby:db2
+        int i = s.indexOf('?');
+
+        return (i == -1 ? s : s.substring(0, i));
+    }
+
+    public static String getDbType(Properties props)
+    {
+        return (String) props.get("db.type");
+    }
+    public static String getDbHost(Properties props)
+    {
+        return (String) props.get("db.host");
+    }
+    public static Integer getDbPort(Properties props)
+    {
+        return (Integer) props.get("db.port");
+    }
+    public static String getDbName(Properties props)
+    {
+        return (String) props.get("db.name");
+    }
+    public static String getDbOpts(Properties props)
+    {
+        return (String) props.get("db.opts");
+    }
+    public static String getDbDriver(Properties props)
+    {
+        return (String) props.get("db.driver");
+    }
+    public static String getDbXADsClass(Properties props)
+    {
+        return (String) props.get("db.xaclass");
+    }
+    public static String getDbUrl(Properties props)
+    {
+        return (String) props.get("db.url");
+    }
+    public static String getDbUser(Properties props)
+    {
+        return (String) props.get("db.user");
+    }
+    public static boolean isEmbedded(Properties props)
+    {
+        return getDbHost(props) == null;
+    }
+    public static String getDbPassword(Properties props)
+    {
+        return (String) props.get("db.password");
+    }
+    public static void shutdownDb(Properties props)
+    {
+        if (isDerby(getDbType(props)) && isEmbedded(props))
+        {
+            String db = getDbName(props);
+
+            try
+            {
+                DriverManager.getConnection("jdbc:derby:" + db + ";shutdown=true");
+            }
+            catch (SQLException e)
+            {
+                // XJ015 and 08006 error codes indicate successfull shutdown
+                if (!"XJ015".equals(e.getSQLState()) && !"08006".equals(e.getSQLState()))
+                    logSQLException(log, e);
+                else if (log.isInfoEnabled())
+                    log.info(e.getMessage());
+            }
+        }
+    }
+
+    public static Xid createJJHXid() {
+        return new XidImple(new Uid());
+    }
+
+    public static void loadDriver(String driverClass)
+    {
+        createInstance(driverClass);
+    }
+
+    public static void loadDriver(Properties props)
+    {
+        loadDriver(getDbDriver(props));
+    }
+
+    public static XADataSource createDataSource(String className)
+    {
+        return (XADataSource) createInstance(className);
+    }
+
+    private static Object createInstance(String className)
+    {
+        try
+        {
+            return Class.forName(className).newInstance();
+        }
+        catch (Exception e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    public static String getDbDriver(String db, boolean isEmbedded)
+    {
+        if (DbWrapper.isMysql(db))
+            return "com.mysql.jdbc.Driver";
+        else if (DbWrapper.isDerby(db))
+            return isEmbedded ? "org.apache.derby.jdbc.EmbeddedDriver" : "org.apache.derby.jdbc.ClientDriver";
+        else if (DbWrapper.isH2(db))
+            return "org.h2.Driver";
+        else
+            return "";
+//        return mysql
+    }
+
+    public static String getDbXADsClass(String db, boolean isEmbedded)
+    {
+        if (DbWrapper.isMysql(db))
+            return "com.mysql.jdbc.jdbc2.optional.MysqlXADataSource";
+        else if (DbWrapper.isPostgresql(db))
+            return "org.postgresql.xa.PGXADataSource";
+        else if (DbWrapper.isDerby(db))
+            return isEmbedded ? "org.apache.derby.jdbc.EmbeddedXADataSource" : "org.apache.derby.jdbc.ClientXADataSource";
+        else if (DbWrapper.isH2(db))
+            return "org.h2.jdbcx.JdbcDataSource";
+        else
+            return "";
+    }
+
+    public static boolean isDerby(String db)
+    {
+        return "derby".equals(db);
+    }
+    public static boolean isH2(String db)
+    {
+        return "h2".equals(db);
+    }
+
+    public static boolean isMysql(String db)
+    {
+        return "mysql".equals(db);
+    }
+
+    public static boolean isPostgresql(String db)
+    {
+        return "postgresql".equals(db);
+    }
+
+    public static boolean isMssql(String db)
+    {
+        return "mssql".equals(db);
+    }
+
+    public static boolean isOracle(String db)
+    {
+        return "oracle".equals(db);
+    }
+
+    public static String initJndi(String bindName)
+    {
+        File jndi = new File(new File(JNDIBASE + bindName).getParent());
+
+        jndi.mkdirs();
+
+        String jndiUrl = "file://" + new File(JNDIBASE).getAbsolutePath();
+
+        // some products take their jndi setting kfrom system properties:
+        System.setProperty("Context.INITIAL_CONTEXT_FACTORY", "com.sun.jndi.fscontext.RefFSContextFactory");
+        System.setProperty("Context.PROVIDER_URL", jndiUrl);
+
+        if (log.isInfoEnabled()) log.info("jndi url: " + jndiUrl);
+
+        return jndiUrl;
+    }
+
+    public static javax.naming.InitialContext jndiBind(String url, String bindName, Object obj) throws NamingException
+    {
+        Hashtable<String, String> env = new Hashtable<String, String> ();
+
+        env.put(javax.naming.Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.fscontext.RefFSContextFactory");
+        env.put(javax.naming.Context.PROVIDER_URL, url);
+
+        javax.naming.InitialContext context = new javax.naming.InitialContext(env);
+
+        context.rebind (bindName, obj);
+
+        return context;
+    }
+
+
+    public static boolean isWarnEnabled(Logger log)
+    {
+        return log.isEnabledFor(org.apache.log4j.Priority.WARN);
+    }
+
+    public static void logSQLException(Logger log, SQLException e)
+    {
+        // Unwraps the entire exception chain to unveil the real cause of the exception
+
+        if (isWarnEnabled(log))
+        {
+            while (e != null)
+            {
+                log.info("\n----- SQLException -----");
+                log.info("  SQL State:  " + e.getSQLState());
+                log.info("  Error Code: " + e.getErrorCode());
+                log.info("  Message:    " + e.getMessage());
+
+                e.printStackTrace();
+                e = e.getNextException();
+            }
+        }
+    }
+
+    private static org.h2.tools.Server server;
+    private static String[] xh2DbUrl = {"jdbc:h2:tcp://172.16.130.129/rc"};
+    static String[] h2DbUrl = {"jdbc:h2:tcp://localhost/rc;user=user1;password=pass1"}; // h2.baseDir sets the base dir for the db
+
+    public static synchronized void startH2Server() throws SQLException
+    {
+        startH2Server(h2DbUrl);
+    }
+
+    public static synchronized void startH2Server(String[] url) throws SQLException
+    {
+        if (server == null)
+            server = org.h2.tools.Server.createTcpServer(url).start();
+
+//        org.h2.jdbcx.JdbcDataSource ds = new org.h2.jdbcx.JdbcDataSource();
+//        ds.setURL(h2DbUrl[0]);
+
+//        ds.setUser("user1");
+//        ds.setPassword("pass1");
+
+//        ds.getConnection();
+        boolean test = false;
+
+        if (test)
+        {
+            java.sql.Connection c = getConnection(h2DbUrl[0]);
+            java.sql.Statement s = c.createStatement();
+
+            s.execute("create table TEST(id int, value varchar(40))");
+            s.close();
+            c.close();
+        }
+    }
+
+    public static synchronized boolean stopDbServer()
+    {
+        if (server != null && server.isRunning(true))
+            server.stop();
+
+        server = null;
+
+        return true;
+    }
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/PerfTest.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/PerfTest.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/PerfTest.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,8 @@
+package com.arjuna.ats.tools.perftest;
+
+public interface PerfTest extends Runnable
+{
+    long getResult();
+
+    Exception getException();
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/TestRunner.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/TestRunner.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/TestRunner.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,186 @@
+package com.arjuna.ats.tools.perftest;
+
+import org.apache.log4j.Logger;
+
+import java.util.Collection;
+import java.util.ArrayList;
+
+import com.arjuna.ats.tools.perftest.product.Product;
+
+public class TestRunner
+{
+    private final static Logger log = Logger.getLogger(Product.class);
+
+    private Collection<Target> tests = new ArrayList<Target>();
+    private long max;
+    private long min;
+    private long avg;
+    private long tot;
+    private int passCount;
+    private long failCount;
+    private ArrayList<Long> times = new ArrayList<Long> ();
+
+    public Object addTest(PerfTest test)
+    {
+        Target t = new Target(test);
+
+        tests.add(t);
+        t.setDaemon(true); // means rogue test won't stop the VM from terminating
+//        t.setPriority(Thread.MAX_PRIORITY);
+
+        return t;
+    }
+
+    public void startTest(Object handle)
+    {
+        Target t = (Target) handle;
+
+        if (tests.contains(t) && !isRunning(t))
+            t.start();
+    }
+
+    public void startTests()
+    {
+        for (Target t : tests)
+            t.run();
+    }
+
+    public boolean isRunning(Object handle)
+    {
+        Target t = (Target) handle;
+
+        return tests.contains(t) && t.isAlive();
+    }
+
+    public void cancelTest(Object t)
+    {
+        ((Thread) t).interrupt();
+    }
+
+    public boolean waitOn()
+    {
+        for (Target t : tests)
+            waitOn(t);
+
+        return (failCount == 0);
+    }
+
+    public boolean waitOn(Object t)
+    {
+        return waitOn(t, 0);
+    }
+
+    public boolean waitOn(Object handle, long timeout)
+    {
+        Target t = (Target) handle;
+
+        if (t.processed)
+            return (t.getResult() != -1);
+
+        if (!tests.contains(t))
+            return false;
+
+        if (isRunning(t))
+        {
+            try
+            {
+                t.join(timeout);
+            }
+            catch (InterruptedException e)
+            {
+            }
+            if (log.isInfoEnabled()) log.info("joined with task " + t.getName() + ": t=" + t.getResult() + " e: " + t.getException());
+        }
+        else
+        {
+            if (log.isInfoEnabled()) log.info("task " + t.getName() + " is not running: t=" + t.getResult() + " e: " + t.getException());
+        }
+
+        long rt = t.getResult();
+
+        t.processed = true;
+
+        if (rt != -1 && t.getException() == null)
+        {
+            times.add(rt);
+            passCount += 1;
+            tot += rt;
+
+            if (rt > max)
+                max = rt;
+            if (rt < min || min == 0)
+                min = rt;
+
+            avg = tot / passCount;
+
+            return true;
+        }
+        else
+        {
+            log.warn("Test " + t.getName() + " failed: " + t.getException());            
+            failCount += 1;
+
+            return false;
+        }
+    }
+
+    public String getTimes()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        for (Long l : times)
+        {
+            sb.append(l).append(',');
+        }
+
+        return sb.toString();
+//        return times.toArray(new Long[times.size()]);
+    }
+
+    public long getMax()
+    {
+        return max;
+    }
+
+    public long getMin()
+    {
+        return min;
+    }
+
+    public long getAvg()
+    {
+        return avg == 0 ? 1 : avg;
+    }
+
+    public int getPassCount()
+    {
+        return passCount;
+    }
+
+    public long getFailCount()
+    {
+        return failCount;
+    }
+
+    private class Target extends Thread
+    {
+        PerfTest test;
+        boolean processed;
+
+        Target(PerfTest target)
+        {
+            super(target);
+            this.test = target;
+        }
+
+        long getResult()
+        {
+            return test.getResult();
+        }
+
+        public Exception getException()
+        {
+            return test.getException();
+        }
+    }
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/AtomikosProduct.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/AtomikosProduct.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/AtomikosProduct.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,80 @@
+package com.arjuna.ats.tools.perftest.product;
+
+import com.atomikos.icatch.config.UserTransactionServiceImp;
+import com.atomikos.icatch.jta.TransactionManagerImp;
+import com.atomikos.icatch.admin.jmx.JmxTransactionService;
+import com.arjuna.ats.tools.perftest.DbWrapper;
+
+import javax.transaction.*;
+import javax.transaction.xa.XAException;
+import javax.sql.DataSource;
+import javax.management.*;
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.util.Properties;
+import java.lang.management.ManagementFactory;
+
+public class AtomikosProduct extends Product
+{
+    public String getName()
+    {   
+        return "Atomikos";
+    }
+
+    protected UserTransaction createTx() throws SystemException, SQLException
+    {
+        if (log.isDebugEnabled()) log.debug("creating Atomikos transaction");
+        
+        return new com.atomikos.icatch.jta.UserTransactionImp();
+    }
+
+    protected void beginTx() throws SystemException, NotSupportedException, SQLException, XAException
+    {
+        super.beginTx();
+    }
+
+    public TransactionManager getTransactionManager()
+    {
+        return com.atomikos.icatch.jta.TransactionManagerImp.getTransactionManager();
+    }
+
+    protected void commitTx(Connection[] connections) throws Exception
+    {
+
+        super.commitTx(connections);    //To change body of overridden methods use File | Settings | File Templates.
+    }
+
+    protected boolean startTxBeforeOpen()
+    {
+        return true;
+    }
+
+    protected boolean supportsDb(String db)
+    {
+        return true;
+    }
+
+    protected void enableJmx() throws JMException
+    {
+        JmxTransactionService service = new JmxTransactionService();
+        MBeanServer jmx = ManagementFactory.getPlatformMBeanServer();
+        ObjectName mBeanName = new ObjectName("atomikos:type=Transactions");
+        jmx.registerMBean(service , mBeanName);
+    }
+
+    protected DataSource createDataSource(String name, Properties props) throws SQLException
+    {
+        if (log.isDebugEnabled()) log.debug("creating Atomikos data source");
+        com.atomikos.jdbc.AtomikosDataSourceBean ds = new com.atomikos.jdbc.AtomikosDataSourceBean();
+
+        ds.setXaDataSourceClassName(DbWrapper.getDbXADsClass(props));
+        ds.setUniqueResourceName(name);
+
+        ds.setPoolSize(4);
+        ds.setXaProperties(DbWrapper.getDbProperties(props));
+
+        if (log.isDebugEnabled()) log.debug("Data source: " + ds.getXaDataSourceClassName());
+
+        return ds;
+    }
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/BitronixProduct.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/BitronixProduct.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/BitronixProduct.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,52 @@
+package com.arjuna.ats.tools.perftest.product;
+
+import bitronix.tm.resource.jdbc.JdbcConnectionHandle;
+
+import javax.transaction.SystemException;
+import javax.transaction.UserTransaction;
+import javax.transaction.TransactionManager;
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.util.Properties;
+
+import com.arjuna.ats.tools.perftest.DbWrapper;
+
+public class BitronixProduct extends Product
+{
+    public String getName()
+    {
+        return "Bitronix";
+    }
+
+    public TransactionManager getTransactionManager()
+    {
+        return bitronix.tm.TransactionManagerServices.getTransactionManager();
+    }
+
+    protected UserTransaction createTx() throws SystemException, SQLException
+    {
+        return bitronix.tm.TransactionManagerServices.getTransactionManager();
+    }
+
+    protected boolean supportsDb(String db)
+    {
+        return true;
+    }
+
+    protected DataSource createDataSource(String name, Properties props) throws SQLException
+    {
+        bitronix.tm.resource.jdbc.PoolingDataSource ds = new bitronix.tm.resource.jdbc.PoolingDataSource();
+
+        ds.setClassName(DbWrapper.getDbXADsClass(props));
+        ds.setUniqueName(name);
+        ds.setMinPoolSize(1);
+        ds.setMaxPoolSize(3);
+        ds.setAutomaticEnlistingEnabled(true);
+        ds.setAllowLocalTransactions(false);
+        ds.setDriverProperties(DbWrapper.getDbProperties(props));
+        ds.setPreparedStatementCacheSize(8);
+        ds.init();  // eagerly initialise the datasource
+
+        return ds;
+    }  
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/JBossTSProduct.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/JBossTSProduct.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/JBossTSProduct.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,92 @@
+package com.arjuna.ats.tools.perftest.product;
+
+import com.arjuna.ats.jdbc.TransactionalDriver;
+import com.arjuna.ats.arjuna.common.arjPropertyManager;
+import com.arjuna.ats.tools.perftest.DbWrapper;
+
+import javax.sql.DataSource;
+import javax.naming.NamingException;
+import javax.transaction.UserTransaction;
+import javax.transaction.SystemException;
+import javax.transaction.TransactionManager;
+import java.io.PrintWriter;
+import java.util.*;
+import java.sql.SQLException;
+import java.sql.Connection;
+
+public class JBossTSProduct extends Product
+{
+    public String getName()
+    {
+        return "JBossTS (" + getStoreType() + ")";
+    }
+
+    public TransactionManager getTransactionManager()
+    {
+        return com.arjuna.ats.jta.TransactionManager.transactionManager();
+    }
+
+    protected UserTransaction createTx() throws SystemException, SQLException
+    {
+        return com.arjuna.ats.jta.UserTransaction.userTransaction();
+    }
+
+    protected boolean supportsDb(String db)
+    {
+        return true;
+    }
+
+    protected String getStoreType()
+    {
+        String st = arjPropertyManager.getObjectStoreEnvironmentBean().getObjectStoreType();
+
+        int ind = st.lastIndexOf('.') + 1;
+
+        return st.substring(ind == 0 ? 0 : ind);
+    }
+
+    protected DataSource createDataSource(String dsName, final Properties props) throws SQLException
+    {
+        String dbName = DbWrapper.getDbName(props);
+        String jndiName = "jdbc/" + dbName;
+        String jndiUrl = DbWrapper.initJndi(jndiName);
+
+        String user = DbWrapper.getDbUser(props);
+        String pass = DbWrapper.getDbPassword(props);
+
+        final String txDriverUrl = TransactionalDriver.arjunaDriver + jndiName; // + ";reuseconnection=true";
+        final DataSource ds = DbWrapper.createDataSource(dsName, props);
+
+        try
+        {
+            DbWrapper.jndiBind(jndiUrl, jndiName, ds);
+        }
+        catch (NamingException e)
+        {
+            if (log.isInfoEnabled()) log.info(e.getMessage() + ": jndi bind " + jndiName + " at " + jndiUrl + " failed.");
+            throw new RuntimeException(e);
+        }
+
+        props.setProperty(com.arjuna.ats.jdbc.TransactionalDriver.userName, user);
+        props.setProperty(com.arjuna.ats.jdbc.TransactionalDriver.password, pass);
+        props.setProperty("reuseconnection", "true");
+
+        return new DataSource() {
+            com.arjuna.ats.jdbc.TransactionalDriver txDriver = new com.arjuna.ats.jdbc.TransactionalDriver();
+
+            public Connection getConnection() throws SQLException {
+                return txDriver.connect(txDriverUrl, props);
+            }
+            public Connection getConnection(String u, String p) throws SQLException {
+                props.setProperty(TransactionalDriver.userName, u);
+                props.setProperty(TransactionalDriver.password, p);
+
+                return txDriver.connect(txDriverUrl, props);
+            }
+            public PrintWriter getLogWriter() throws SQLException {return ds.getLogWriter();}
+            public void setLogWriter(PrintWriter out) throws SQLException {ds.setLogWriter(out);}
+            public void setLoginTimeout(int seconds) throws SQLException {ds.setLoginTimeout(seconds);}
+            public int getLoginTimeout() throws SQLException {return ds.getLoginTimeout();}
+        };
+    }
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/JOTMProduct.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/JOTMProduct.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/JOTMProduct.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,146 @@
+package com.arjuna.ats.tools.perftest.product;
+
+import com.arjuna.ats.tools.perftest.DbWrapper;
+
+import javax.transaction.UserTransaction;
+import javax.transaction.SystemException;
+import javax.transaction.InvalidTransactionException;
+import javax.transaction.TransactionManager;
+import javax.transaction.xa.XAException;
+import javax.sql.DataSource;
+import javax.sql.XADataSource;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.util.Properties;
+import java.io.PrintWriter;
+
+public class JOTMProduct extends Product
+{
+    private static final String JNDIBINDNAME = "UserTransaction";
+
+    private org.objectweb.jotm.Jotm jotm;
+    private boolean useJndi = true;
+    private String jndiUrl;
+    private javax.naming.InitialContext context;
+
+    public String getName()
+    {
+        return "JOTM";
+    }
+
+    public TransactionManager getTransactionManager()
+    {
+        return jotm.getTransactionManager();
+    }
+
+    protected void init(Connection c, Properties props) throws SQLException
+    {
+        if (useJndi)
+            jndiUrl = DbWrapper.initJndi(JNDIBINDNAME);
+    }
+
+    public void fini()
+    {
+        if (useJndi)
+        {
+            try
+            {
+                context.unbind(JNDIBINDNAME);
+            }
+            catch (Exception e)
+            {
+                throw new RuntimeException(e);
+            }
+        }
+
+        org.objectweb.jotm.TimerManager.stop();
+        jotm.stop();
+    }
+
+    protected UserTransaction createTx() throws SystemException, SQLException
+    {
+        if (useJndi)
+        {
+            try
+            {
+                return (UserTransaction) context.lookup(JNDIBINDNAME);
+            }
+            catch (NamingException e)
+            {
+                throw new RuntimeException(e);
+            }
+        }
+        else
+        {
+            try
+            {
+                return (UserTransaction) new InitialContext().lookup("UserTransaction");
+            }
+            catch (NamingException e)
+            {
+                throw new SystemException(e.getMessage());
+            }
+//            return jotm.getUserTransaction();
+        }
+    }
+
+    protected boolean supportsDb(String db)
+    {
+        return true;
+    }
+
+    // StandardXAConnection does not support suspend and resume
+    protected void suspendTx() throws SQLException, XAException, SystemException
+    {
+    }
+
+    protected void resumeTx() throws SQLException, XAException, SystemException, InvalidTransactionException
+    {
+    }
+
+    protected DataSource createDataSource(String name, final Properties props) throws SQLException
+    {
+        // Get a transction manager
+
+        try
+        {
+            // creates an instance of JOTM with a local transaction factory which is not bound to a registry
+            jotm = new org.objectweb.jotm.Jotm(true, false);
+            if (useJndi)
+                context = DbWrapper.jndiBind(jndiUrl, JNDIBINDNAME, jotm.getUserTransaction());
+        }
+        catch (NamingException e)
+        {
+            throw new RuntimeException(e);
+        }
+
+        final XADataSource xads = new org.enhydra.jdbc.standard.StandardXADataSource();
+
+        try
+        {
+            ((org.enhydra.jdbc.standard.StandardXADataSource) xads).setDriverName(DbWrapper.getDbDriver(props));
+            ((org.enhydra.jdbc.standard.StandardXADataSource) xads).setUrl(DbWrapper.getDbUrl(props));
+            ((org.enhydra.jdbc.standard.StandardXADataSource) xads).setTransactionManager(jotm.getTransactionManager());
+        }
+        catch (Exception e)
+        {
+            e.printStackTrace();
+            System.exit(1);
+        }
+
+        return new DataSource() {
+            public Connection getConnection() throws SQLException {
+                return getConnection(DbWrapper.getDbUser(props), DbWrapper.getDbPassword(props));
+            }
+            public Connection getConnection(String u, String p) throws SQLException {
+                return xads.getXAConnection(u, p).getConnection();
+            }
+            public PrintWriter getLogWriter() throws SQLException {return xads.getLogWriter();}
+            public void setLogWriter(PrintWriter out) throws SQLException {xads.setLogWriter(out);}
+            public void setLoginTimeout(int seconds) throws SQLException {xads.setLoginTimeout(seconds);}
+            public int getLoginTimeout() throws SQLException {return xads.getLoginTimeout();}
+        };
+    }
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/NonXAProduct.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/NonXAProduct.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/NonXAProduct.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,55 @@
+package com.arjuna.ats.tools.perftest.product;
+
+import com.arjuna.ats.tools.perftest.product.Product;
+import com.arjuna.ats.tools.perftest.DbWrapper;
+
+import javax.sql.DataSource;
+import javax.transaction.*;
+import java.util.Properties;
+import java.sql.SQLException;
+import java.sql.Connection;
+
+public class NonXAProduct extends Product
+{
+    public String getName()
+    {
+        return "NonXA";
+    }
+
+    protected void commitTx(Connection[] connections) throws Exception
+    {
+        for (Connection c : connections)
+            c.commit();
+    }
+
+    protected void closeConnection(Connection c) throws SQLException
+    {
+        c.commit();
+        c.close();
+    }
+
+    protected boolean supportsDb(String db)
+    {
+        return true;
+    }
+
+    protected DataSource createDataSource(String name, Properties props) throws SQLException
+    {
+        return DbWrapper.createDataSource(name, props);
+    }
+
+    public TransactionManager getTransactionManager()
+    {
+        return new TransactionManager() {
+            public void begin() throws NotSupportedException, SystemException {}
+            public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException, RollbackException, SecurityException, SystemException {}
+            public int getStatus() throws SystemException {return 0;}
+            public Transaction getTransaction() throws SystemException {return null;}
+            public void resume(Transaction transaction) throws IllegalStateException, InvalidTransactionException, SystemException {}
+            public void rollback() throws IllegalStateException, SecurityException, SystemException {}
+            public void setRollbackOnly() throws IllegalStateException, SystemException {}
+            public void setTransactionTimeout(int i) throws SystemException {}
+            public Transaction suspend() throws SystemException {return null;}
+        };
+    }
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/Product.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/Product.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/Product.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,809 @@
+package com.arjuna.ats.tools.perftest.product;
+
+import org.apache.log4j.Logger;
+
+import javax.transaction.*;
+import javax.transaction.xa.XAException;
+import javax.sql.DataSource;
+import javax.management.JMException;
+import java.sql.*;
+import java.util.*;
+import java.io.*;
+
+import com.arjuna.ats.tools.perftest.DbWrapper;
+import com.arjuna.ats.tools.perftest.TestRunner;
+import com.arjuna.ats.tools.perftest.PerfTest;
+
+/**
+ * Base class that each transaction prodcut should subclass. The main method controls test execution -
+ * if any of the default behaviours supplied by this base class are not appropriate each product should
+ * override that behaviour. Please consult subclasses for examples.
+ */
+public abstract class Product
+{
+    /**
+     * Provide a human readable name for the product being tested
+     * @return name of the product
+     */
+    public abstract String getName();
+
+    /**
+     * A compliant product implements TransactionManager
+     * @return the products implementation of TransactionManager
+     */
+    public abstract TransactionManager getTransactionManager();
+
+    /**
+     * Some products require their own wrappers around javax.sql.DataSource
+     * This method may be overridden to support such a product
+     * @param name a name for the resource
+     * @param props set of properties to set on the underlying resource manager
+     * @return a wrapped data source
+     * @throws SQLException
+     */
+    protected abstract DataSource createDataSource(String name, Properties props) throws SQLException;
+
+    /**
+     * Tests whether the product supports a particular database
+     * @param db the database name that was extracted from the connect URL
+     * @return true if the product works with the database
+     */
+    protected abstract boolean supportsDb(String db);
+
+    public static void main(String[] args) throws Exception
+    {
+//        DbWrapper.startH2Server();
+
+        // set up the test
+        initialize(args);
+
+        // and test each product
+        for (prodIndex = 0; prodIndex < products.size(); prodIndex++)
+            products.get(prodIndex).runTest();
+
+        // write out the test results
+        if (results != null)
+            results.close();
+
+        if (csvWriter != null)
+        {
+            for (Object[] row : csv)
+            {
+                for (Object val : row)
+                {
+                    csvWriter.print(val);
+                    csvWriter.print(',');
+                }
+
+                csvWriter.println();
+            }
+
+            csvWriter.close();
+        }
+
+        for (Properties p : urls.values())
+            DbWrapper.shutdownDb(p);
+
+//        DbWrapper.stopDbServer();
+    }
+
+    protected void enableJmx() throws JMException
+    {
+    }
+
+    protected void init(Connection c, Properties props) throws SQLException
+    {
+    }
+
+    protected void init(Properties props)
+    {
+    }
+
+    protected UserTransaction createTx() throws SystemException, SQLException
+    {
+        return null;
+    }
+
+    protected void beginTx() throws SystemException, NotSupportedException, SQLException, XAException
+    {
+        if (ut != null)
+            ut.begin();
+    }
+
+    protected void commitTx(Connection[] connections) throws Exception
+    {
+//        suspendTx();
+//        resumeTx();
+        if (log.isInfoEnabled()) log.info("commit: ut=" + ut);
+        if (ut != null)
+            ut.commit();
+    }
+
+    protected void rollbackTx() throws SystemException, NotSupportedException
+    {
+        if (log.isInfoEnabled()) log.info("rollback: ut=" + ut);
+        if (ut != null)
+            ut.rollback();
+    }
+
+    protected void suspendTx() throws SQLException, XAException, SystemException
+    {
+        tx = getTransactionManager().suspend();
+    }
+
+    protected void resumeTx() throws SQLException, XAException, SystemException, InvalidTransactionException
+    {
+        getTransactionManager().resume(tx);
+    }
+
+    protected void openConnections(Connection[] connections) throws SQLException
+    {
+        for (int i = 0; i < dataSources.length; i++)
+        {
+            connections[i] = dataSources[i].getConnection();
+            connections[i].setAutoCommit(false);
+        }
+    }
+
+    protected void closeConnection(Connection c) throws SQLException
+    {
+        if (c != null && !c.isClosed())
+            c.close();
+    }
+
+    private void closeConnections(Connection[] connections)
+    {
+        for (Connection c : connections)
+        {
+            try
+            {
+                closeConnection(c);
+            }
+            catch (SQLException e)
+            {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    protected void fini()
+    {
+    }
+
+    protected void executeStatement(Connection c, String sql, Object ... args) throws SQLException
+    {
+        executeStatement(prepareStatement(c, sql), args);
+    }
+
+    protected void executeStatement(PreparedStatement s, Object ... args) throws SQLException
+    {
+        for (int i = 0; i < args.length; i++)
+            s.setObject(i + 1, args[i]);
+
+        s.executeUpdate();
+    }
+
+    protected PreparedStatement prepareStatement(Connection c, String sql) throws SQLException
+    {
+        PreparedStatement ps = c.prepareStatement(sql);
+
+        statements.add(ps);
+
+        return ps;
+    }
+
+    protected void executeSql(Connection c, String sql, boolean ignoreErrors) throws SQLException
+    {
+        Statement s = c.createStatement();
+
+        statements.add(s);
+
+        if (log.isDebugEnabled()) log.debug("executeSql() " + sql);
+        try
+        {
+            s.execute(sql);
+        }
+        catch (SQLException e)
+        {
+            if (!ignoreErrors)
+                throw e;
+
+            if (log.isDebugEnabled()) log.debug("executeSql() " + e.getMessage());
+        }
+    }
+
+    /**
+     * Some products require an active tx for resources to be automatically
+     * enlisted on open
+     *
+     * @return true if a tx must be active for automatic enlistment
+     */
+    protected boolean startTxBeforeOpen()
+    {
+        return false;
+    }
+
+    private static void addUrl(String url)
+    {
+        int i = url.indexOf('=') + 1;
+
+        if (i == 0 || i == url.length())
+            throw new IllegalArgumentException("Invalid jdbc url: " + url);
+
+        urls.put(url.substring(i), new Properties());
+    }
+
+    private static int[] parseIntArray(String sa)
+    {
+        String[] va = sa.split(",");
+        int[] values = new int[va.length];
+
+        for (int i = 0; i < va.length; i++)
+            values[i] = Integer.parseInt(va[i]);
+
+        return values;
+    }
+
+    private static void initialize(String[] args) throws IllegalArgumentException
+    {
+        String[] users = null;
+        String[] passwords = null;
+        String xargs = System.getProperty("xargs");
+        Set<String> dbs = new HashSet<String> ();
+        Properties testProps = new Properties();
+        Properties runProps = new Properties();
+
+        for (String arg : args)
+        {
+            int ind = arg.indexOf('=');
+
+            if (ind != -1 && ind + 1 != arg.length())
+                runProps.setProperty(arg.substring(0, ind), arg.substring(ind + 1));
+        }
+
+        testProps.put("tx.count", "1");
+        testProps.put("debug", "0");
+
+        for (String arg : args)
+        {
+            if (arg.startsWith(TXCOUNT_PROP + '='))
+                TXCOUNT = parseIntArray(arg.split("=")[1]);
+            else if (arg.startsWith(THRCOUNT_PROP + '='))
+                THRCOUNT = parseIntArray(arg.split("=")[1]);
+            else if (arg.startsWith(DEBUG_PROP + '='))
+                testProps.put(DEBUG_PROP, arg.split("=")[1]);
+            else if (arg.startsWith(DEBUGLOG_PROP + '='))
+                testProps.put(DEBUGLOG_PROP, arg.split("=")[1]);
+            else if (arg.startsWith(PRODUCTS_PROP + '='))
+                testProps.put(PRODUCTS_PROP, arg.split("=")[1]);
+            else if (arg.startsWith(DB_URL_PROP + '='))
+                addUrl(arg);
+            else if (arg.startsWith(DB_USER_PROP + '='))
+                users = arg.split("=")[1].split(",", -1);
+            else if (arg.startsWith(DB_PASSWORD_PROP + '='))
+                passwords = arg.split("=")[1].split(",", -1);
+            else if (arg.startsWith(RESULT_FILE_PROP + '='))
+                openResults(arg.split("=")[1]);
+            else if (arg.startsWith(CSV_FILE_PROP + '='))
+                csvWriter = openFileWriter(arg.split("=")[1], true);
+        }
+
+        if (xargs != null)
+        {
+            for (String arg : xargs.split("%"))
+            {
+            if (arg.startsWith(TXCOUNT_PROP + '='))
+                TXCOUNT = parseIntArray(arg.split("=")[1]);
+            else if (arg.startsWith(THRCOUNT_PROP + '='))
+                THRCOUNT = parseIntArray(arg.split("=")[1]);
+            else if (arg.startsWith(DEBUG_PROP + '='))
+                testProps.put(DEBUG_PROP, arg.split("=")[1]);
+            else if (arg.startsWith(DEBUGLOG_PROP + '='))
+                testProps.put(DEBUGLOG_PROP, arg.split("=")[1]);
+            else if (arg.startsWith(PRODUCTS_PROP + '='))
+                testProps.put(PRODUCTS_PROP, arg.split("=")[1]);
+            else if (arg.startsWith(DB_URL_PROP + '='))
+                addUrl(arg);
+            else if (arg.startsWith(DB_USER_PROP + '='))
+                users = arg.split("=")[1].split(",", -1);
+            else if (arg.startsWith(DB_PASSWORD_PROP + '='))
+                passwords = arg.split("=")[1].split(",", -1);
+            else if (arg.startsWith(RESULT_FILE_PROP + '='))
+                openResults(arg.split("=")[1]);
+            else if (arg.startsWith(CSV_FILE_PROP + '='))
+                csvWriter = openFileWriter(arg.split("=")[1], false);
+            else if (arg.startsWith(SYNC_PROP + '='))
+                runProps.put(SYNC_PROP, arg.split("=")[1]);
+            else if (arg.startsWith(STORE_PROP + '='))
+                runProps.put(STORE_PROP, arg.split("=")[1]);
+            else if (arg.startsWith(DELAY_PROP + '='))
+                runProps.put(DELAY_PROP, arg.split("=")[1]);
+            }
+        }
+/*
+        if (urls.size() == 0)
+            throw new RuntimeException("Please specify one or more jdbc connect urls using the syntax " + DB_URL_PROP + "=<connect url>");
+
+        if (users == null || passwords == null || users.length != passwords.length || users.length < urls.size())
+            throw new RuntimeException("The number of db urls, users and passwords are not equal");
+*/
+        int i = 0;
+
+        for (Map.Entry<String, Properties> me : urls.entrySet())
+        {
+            Properties p = me.getValue();
+            String url = me.getKey();
+
+            p.put(DB_USER_PROP, users[i]);
+            p.put(DB_PASSWORD_PROP, passwords[i++]);
+
+            DbWrapper.parseUrl(url, p);
+
+            dbs.add(DbWrapper.getDbType(p));
+            p.putAll(testProps);
+            DbWrapper.loadDriver(p);
+        }
+
+        // add the relevant drivers to the jdbc.drivers system property
+/*
+        StringBuilder sb = new StringBuilder();
+        for (String db : dbs)
+        {
+            if (sb.length() != 0)
+                sb.append(':');
+
+            sb.append(db);
+        }
+        System.getProperties().put("jdbc.drivers", sb.toString());
+*/
+
+        String pprop = System.getProperty(PRODUCTS_PROP);
+
+        if (pprop == null || pprop.length() == 0)
+            pprop = (String) testProps.get(PRODUCTS_PROP);
+
+        if (pprop != null && pprop.length() != 0)
+        {
+            for (String clazz : pprop.split(","))
+            {
+                Product p = null;
+                boolean canRun = false;
+                try
+                {
+                    p = loadProduct(clazz);
+                    p.init(runProps);
+                    canRun = true;
+
+                    for (String type : dbs)
+                    {
+                        if (!p.supportsDb(type))
+                        {
+                            if (DbWrapper.isWarnEnabled(log)) log.warn("Product " + p.getName() + " does not support db type " + type);
+                            canRun = false;
+                        }
+                    }
+                }
+                catch (IllegalArgumentException e)
+                {
+                    if (DbWrapper.isWarnEnabled(log)) log.warn("Error initializing product " + clazz + ": " + e.getMessage());
+                    //e.printStackTrace();
+                }
+
+                if (canRun)
+                {
+                    try
+                    {
+                        p.enableJmx();
+                        products.add(p);
+                    }
+                    catch (JMException e)
+                    {
+                        if (DbWrapper.isWarnEnabled(log)) log.warn("Product " + p.getName() + ": JMX error: " + e.getMessage());
+                    }
+                }
+            }
+        }
+
+        if (csvWriter != null)
+        {
+            // create array to hold results. Add 1 to row count for the headers
+            // and add 2 to col count to include thread and tx count columns
+            csv = new Object[1 + THRCOUNT.length][2 + products.size()];
+            csv[0][0] = "Threads";
+            csv[0][1] = "Tx";
+
+            for (i = 0; i < products.size(); i++)
+                csv[0][i + 2] = products.get(i).getName();
+
+            for (i = 1; i <= THRCOUNT.length; i++)
+            {
+                for (int j = 0; j < TXCOUNT.length; j++)
+                {
+                    csv[i][0] = THRCOUNT[i - 1];
+                    csv[i][1] = TXCOUNT[j];
+                }
+            }
+        }
+    }
+
+    private static Product loadProduct(String className) throws IllegalArgumentException
+    {
+        try
+        {
+            return (Product) Class.forName(className).newInstance();
+        }
+        catch (ClassCastException e)
+        {
+            throw new IllegalArgumentException(className + " does not extend Product");
+        }
+        catch (Exception e)
+        {
+            throw new IllegalArgumentException("Unable to instantiate " + className + ": " + e.getMessage());
+        }
+    }
+
+    private void setup() throws SQLException
+    {
+        int i = 0;
+
+        dataSources = new DataSource[urls.size()];
+        DataSource[] adminDs = new DataSource[urls.size()];
+
+        for (Properties p : urls.values())
+        {
+            DataSource ds = new NonXAProduct().createDataSource("nonXA", p);
+            Connection c = ds.getConnection();
+            String name = DbWrapper.getDbName(p);
+
+            c.setAutoCommit(false);
+
+            executeSql(c, "CREATE SCHEMA " + name, true);
+            executeSql(c, SQLT1.replace("$DB", name), true);
+            executeSql(c, SQLT2.replace("$DB", name), true);
+
+            init(c, p);
+            c.commit();
+            c.close();
+
+            adminDs[i] = ds;
+
+            dataSources[i] = createDataSource("ds" + i, p);
+            i += 1;
+        }
+    }
+
+    private void runTest()
+    {
+        if (log.isDebugEnabled()) log.debug("Testing product " + getName());
+
+        try
+        {
+            setup();
+            ut = createTx();
+
+            try
+            {
+
+                test(new TestRunner(), 1, 1);
+
+                for (int i = 0; i < THRCOUNT.length; i++)
+                {
+                    for (int j = 0; j < TXCOUNT.length; j++)
+                    {
+                        TestRunner tr = test(new TestRunner(), THRCOUNT[i], TXCOUNT[j]);
+
+                        writeResults(tr, TXCOUNT[j]);
+//                        csv[i + 1][prodIndex + 2] = (float) tr.getAvg() / TXCOUNT[j];
+                        csv[i + 1][prodIndex + 2] = TXCOUNT[j] * 1000 / tr.getAvg();
+                    }
+                }
+            }
+            catch (SQLException e)
+            {
+                DbWrapper.logSQLException(log, e);
+                rollbackTx();
+            }
+        }
+        catch (SQLException e)
+        {
+            DbWrapper.logSQLException(log, e);
+        }
+        catch (Throwable e)
+        {
+            log.error("Fatal: " + e.getMessage());
+            e.printStackTrace();
+        }
+        finally
+        {
+            releaseResources();
+        }
+    }
+
+    private void releaseResources()
+    {
+        if (log.isInfoEnabled()) log.info("releasing resources");
+
+        for (Statement statement : statements)
+        {
+            try
+            {
+                if (statement != null)
+                    statement.close();
+            }
+            catch (SQLException sqle) {
+                DbWrapper.logSQLException(log, sqle);
+            }
+        }
+
+        fini();
+    }
+
+
+    private String[] replaceSql(String sql)
+    {
+        String[] sqla = new String[urls.size()];
+        int i = 0;
+
+        for (Properties p : urls.values())
+            sqla[i++] = sql.replace("$DB", DbWrapper.getDbName(p));
+
+        return sqla;
+    }
+
+    private TestRunner test(TestRunner tr, int threadCount, int txCount) throws Exception
+    {
+        for (int i = 0; i < threadCount; i++)
+            tr.addTest(getTest(String.valueOf(i), txCount));
+
+        tr.startTests();
+        tr.waitOn();
+
+        return tr;
+    }
+
+    private PerfTest getTest(final String name, final int txCount)
+    {
+        return new PerfTest() {
+            private long rt = -1;
+            private Exception exception;
+            private String n = name;
+            private int count = txCount;
+
+            public long getResult()
+            {
+                return rt;
+            }
+
+            public String getName()
+            {
+                return n;
+            }
+
+            public int getTxCount()
+            {
+                return count;
+            }
+
+            public Exception getException()
+            {
+                return exception;
+            }
+
+            public void run()
+            {
+                try
+                {
+                    if (log.isInfoEnabled()) log.info("Test " + Thread.currentThread().getName() + " is starting ...");
+                    String[] sql = replaceSql(SQLT1_I);
+                    Connection[] connections = new Connection[dataSources.length];
+
+                    if (!startTxBeforeOpen())
+                        openConnections(connections);
+                    
+                    long t = System.currentTimeMillis();
+                    PreparedStatement ps = null;
+
+                    for (int cnt = 0; cnt < txCount; cnt++)
+                    {
+                        boolean started = false;
+
+                        try
+                        {
+                            beginTx();
+                            started = true;
+
+                            if (startTxBeforeOpen())
+                                openConnections(connections);
+
+                            for (int i = 0; i < connections.length; i++)
+                            {
+                                try
+                                {
+                                    ps = prepareStatement(connections[i], sql[i]);
+                                    executeStatement(ps, cnt, "Text");
+                                }
+                                catch (SQLException e)
+                                {
+                                    log.error("Transaction #" + cnt + " db: " + i);
+                                    e.printStackTrace();
+                                    throw e;
+                                }
+                                finally
+                                {
+                                    if (ps != null)
+                                        ps.close();
+                                }
+                            }
+
+                            if (cnt % 10 == 0 && cnt > 0)
+                                Thread.yield();
+
+                            if (startTxBeforeOpen())
+                                closeConnections(connections);
+                            commitTx(connections);
+                            started = false;
+                        }
+                        finally
+                        {
+                            if (started)
+                            {
+                                try
+                                {
+                                    rollbackTx();
+                                }
+                                catch (Exception e)
+                                {
+                                    exception = e;
+                                    log.error(e.getMessage());
+                                }
+                            }
+                        }
+                    }
+
+                    rt = System.currentTimeMillis() - t;
+
+                    if (!startTxBeforeOpen())
+                        closeConnections(connections);
+                }
+                catch (Exception e)
+                {
+                    exception = e;
+                    log.error(e.getMessage());
+                }
+
+                if (log.isInfoEnabled()) log.info("Test " + Thread.currentThread().getName() + " has finished");
+            }
+        };
+    }
+
+    private void writeResults(TestRunner tr, int txCount) throws SQLException
+    {
+        StringBuilder types = new StringBuilder();
+
+        for (Properties p : urls.values())
+        {
+            if (types.length() != 0)
+                types.append(',');
+            types.append(DbWrapper.getDbType(p));
+        }
+/*
+        String[] sql = replaceSql(SQLT2_I);
+
+        for (int i = 0; i < sql.length; i++)
+        {
+            Connection c = adminDs[i].getConnection();
+            executeStatement(c, sql[i], getName(), types.toString(), tr.getPassCount(), tr.getFailCount(), tr.getMax(), tr.getMin(), tr.getAvg(), txCount);
+            c.commit();
+            c.close();
+        }
+*/
+        //%[argument_index$][flags][width][.precision]conversion
+        int tp = (int) (txCount * 1000 / tr.getAvg());
+        
+        results.format("%1$-32s %2$-16s %3$-8d %4$-8d %5$-8d %6$-8d %7$-8d %8$-8d %9$-9d\n", // %10$-32s\n", //%9$7.2f\n",
+                getName(), types.toString(), tr.getPassCount(), tr.getFailCount(), tr.getMax(), tr.getMin(), tr.getAvg(), txCount,
+                tp); //, tr.getTimes()); //(float) tr.getAvg() / txCount);
+        System.out.println(getName() + '\t' + txCount + '\t' + txCount * 1000 / tr.getAvg());
+    }
+
+    private static PrintWriter openFileWriter(String fileName, boolean append)
+    {
+        System.out.println("output file: " + fileName);
+        try
+        {
+            return new PrintWriter(new FileOutputStream(fileName, append));
+        }
+        catch (FileNotFoundException e)
+        {
+            throw new IllegalArgumentException("Error opening resuts file: " + e.getMessage());
+        }
+    }
+
+    private static void openResults(String fileName)
+    {
+        System.out.println("output file: " + fileName);
+        try
+        {
+            File file = new File(fileName);
+            boolean exists = file.exists();
+
+            if ("true".equals(System.getProperty("results")))
+            {
+                if (exists)
+                {
+                    InputStream in = new FileInputStream(file);
+                    OutputStream out = System.out;
+                    byte[] buf = new byte[1024];
+                    int len;
+
+                    try
+                    {
+                        while ((len = in.read(buf)) > 0)
+                            out.write(buf, 0, len);
+
+                        in.close();
+                    }
+                    catch (IOException e)
+                    {
+                        e.printStackTrace();
+                    }
+                }
+
+                System.exit(0);
+            }
+
+            results = openFileWriter(fileName, true);
+
+            if (!exists)
+            {
+                results.format("%1$-32s %2$-16s %3$-8s %4$-8s %5$-8s %6$-8s %7$-8s %8$-8s %9$8s\n",
+                        "Product", "Database(s)", "Pass", "Fail", "Max", "Min", "Average", "Count", "tx/sec");
+                results.format("%1$-32s %2$-16s %3$-8s %4$-8s %5$-8s %6$-8s %7$-8s %8$-8s %9$8s\n",
+                        "------", "-----------", "----", "----", "---", "---", "-------", "-----", "------");
+            }
+        }
+        catch (FileNotFoundException e)
+        {
+            throw new IllegalArgumentException("Error opening resuts file: " + e.getMessage());
+        }
+    }
+
+    protected final static Logger log = Logger.getLogger(Product.class);
+
+    private static String SQLT1 = "create table $DB.TEST(id int, value varchar(40))";
+    private static String SQLT1_I = "insert into $DB.TEST values (?, ?)";
+    private static String SQLT2 = "create table $DB.RESULT(product varchar(64), dbvendor varchar(32), pass int, fail int, maxt int, mint int, avgt int, count int)";
+    private static String SQLT2_I = "insert into $DB.RESULT values (?, ?, ?, ?, ?, ?, ?, ?)";
+
+    protected static final String DB_URL_PROP = "db.url";
+    protected static final String DB_USER_PROP = "db.user";
+    protected static final String DB_PASSWORD_PROP = "db.password";
+    protected static final String PRODUCTS_PROP = "products";
+    protected static final String DEBUG_PROP = "debug.level";
+    protected static final String DEBUGLOG_PROP = "debug.file";
+    protected static final String RESULT_FILE_PROP = "result.file";
+    protected static final String CSV_FILE_PROP = "csv.file";
+    protected static final String TXCOUNT_PROP = "tx.count";
+    protected static final String THRCOUNT_PROP = "thread.count";
+    protected static final String SYNC_PROP = "store.sync";
+    protected static final String DELAY_PROP = "store.asyncTypes";
+    protected static final String STORE_PROP = "store.types";
+    protected static final String CSV_PROP = "csv";
+
+    private static List<Product> products = new ArrayList<Product> ();
+    private static Map<String, Properties> urls = new LinkedHashMap<String, Properties> ();
+
+    private static int[] TXCOUNT = {100};
+    private static int[] THRCOUNT = {1};
+
+    private static PrintWriter results;
+    private static PrintWriter csvWriter;
+    private static Object[][] csv;
+    private static int prodIndex;
+
+    private List<Statement> statements = new ArrayList<Statement> ();
+    private javax.transaction.UserTransaction ut;
+    private Transaction tx;
+
+    private DataSource[] dataSources;
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/SimpleJTAProduct.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/SimpleJTAProduct.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/SimpleJTAProduct.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,153 @@
+package com.arjuna.ats.tools.perftest.product;
+
+import com.arjuna.ats.tools.perftest.product.Product;
+import com.arjuna.ats.tools.perftest.DbWrapper;
+
+import javax.transaction.*;
+import javax.sql.DataSource;
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.util.Properties;
+
+public class SimpleJTAProduct extends Product
+{
+    private static final String TMID = "TMGR.1";
+
+    private Properties simpleJtaProps;
+
+    public String getName()
+    {
+        return "SimpleJTA";
+    }
+
+    public TransactionManager getTransactionManager()
+    {
+        try
+        {
+            return org.simplejta.tm.SimpleTransactionManager.getTransactionManager(simpleJtaProps);
+        }
+        catch (SystemException e)
+        {
+            throw new RuntimeException(e);
+        }
+    }
+
+    // WARNING putting a schema qualifier here means simpleJTA won't be able to find its logs
+    // see  org.simplejta.tm.log.JDBCTransactionLog
+    private static final String SJTA_CREATE1_SQL =
+            "create table app.sjta_transactions (" +
+                    "    tid bigint generated always as identity," +
+                    "    tmid varchar(30)," +
+                    "    formatid int," +
+                    "    gtid varchar(64) for bit data," +
+                    "    bqual varchar(64) for bit data," +
+                    "    state smallint" +
+                    ")";
+    private static final String SJTA_CREATE2_SQL =
+            "create table app.sjta_transaction_branches (" +
+                    "       tid bigint," +
+                    "       bid int," +
+                    "       formatid int," +
+                    "       gtid varchar(64) for bit data," +
+                    "       bqual varchar(64) for bit data," +
+                    "       state smallint," +
+                    "       url varchar(128)," +
+                    "       userid varchar(30)," +
+                    "       password varchar(30)," +
+                    "       typeid varchar(30)" +
+                    ")";
+
+    protected void init(Connection c, Properties props) throws SQLException
+    {
+        if (log.isDebugEnabled()) log.debug("init simpleJTA");
+
+        String user = DbWrapper.getDbUser(props);
+        String pass = DbWrapper.getDbPassword(props);
+        String url = DbWrapper.getDbUrl(props);
+        String db = DbWrapper.getDbName(props);
+
+url = "jdbc:derby://localhost:1527/rc;create=true";
+user = "app";
+pass = "app";
+
+//url = "jdbc:h2:tcp://localhost/rc;user=user1;password=pass1";
+        
+
+        simpleJtaProps = new Properties();
+
+        simpleJtaProps.setProperty(org.simplejta.tm.SimpleTransactionManager.STM_TMGR_ID,
+                TMID);
+//        simpleJtaProps.setProperty(org.simplejta.tm.SimpleTransactionManager.STM_TMGR_RECO_USER,
+//                user);
+//        simpleJtaProps.setProperty(org.simplejta.tm.SimpleTransactionManager.STM_TMGR_RECO_PW,
+//                pass);
+        simpleJtaProps.setProperty(org.simplejta.tm.log.TransactionLogFactory.STM_TLOG_DRIVER,
+                org.simplejta.tm.datasource.DerbyXAConnectionFactory.TYPEID);
+        simpleJtaProps.setProperty(org.simplejta.tm.log.TransactionLogFactory.STM_TLOG_URL,
+                url); //url); //DERBY_URL_PROP));
+        simpleJtaProps.setProperty(org.simplejta.tm.log.TransactionLogFactory.STM_TLOG_USER,
+                user);
+        simpleJtaProps.setProperty(org.simplejta.tm.log.TransactionLogFactory.STM_TLOG_PASSWORD,
+                pass);
+
+// Never use an embedded db logging and recovery with SimpleJTA
+//        c = DbWrapper.getConnection(url);
+DbWrapper.loadDriver("org.apache.derby.jdbc.ClientDriver");
+c = DriverManager.getConnection(url);
+c.setAutoCommit(false);
+        executeSql(c, SJTA_CREATE1_SQL, true);
+        executeSql(c, SJTA_CREATE2_SQL, true);
+c.commit();
+c.close();
+    }
+
+    protected void fini()
+    {
+        org.simplejta.tm.SimpleTransactionManager tmgr;
+        try
+        {
+            tmgr = org.simplejta.tm.SimpleTransactionManager.getTransactionManager(simpleJtaProps);
+            tmgr.shutdown();
+        }
+        catch (SystemException e)
+        {
+            e.printStackTrace();
+        }
+    }
+
+    protected UserTransaction createTx() throws SystemException, SQLException
+    {
+        return new org.simplejta.tm.ut.SimpleUserTransaction(simpleJtaProps);
+    }
+
+    protected boolean supportsDb(String db)
+    {
+        return DbWrapper.isDerby(db) || DbWrapper.isPostgresql(db) || DbWrapper.isOracle(db) || DbWrapper.isMssql(db);
+    }
+
+    protected DataSource createDataSource(String name, Properties props) throws SQLException
+    {
+        String type = DbWrapper.getDbType(props);
+        String db = DbWrapper.getDbName(props);
+        String user = DbWrapper.getDbUser(props);
+        String pass = DbWrapper.getDbPassword(props);
+        String url = DbWrapper.getDbUrl(props);
+
+        if (DbWrapper.isDerby(type))
+            return new org.simplejta.tm.datasource.SimpleDerbyXADataSource(TMID, db, user, pass);
+        else if (DbWrapper.isPostgresql(type))
+            return new org.simplejta.tm.datasource.SimplePostgreSqlXADataSource(TMID, url, user, pass); //TODO url -> properties
+        else if (DbWrapper.isOracle(type))
+            return new org.simplejta.tm.datasource.SimpleOracleXADataSource(TMID, url, user, pass);
+        else if (DbWrapper.isMssql(type))
+            return new org.simplejta.tm.datasource.SimpleMsSqlServerXADataSource(TMID, url, user, pass); //TODO url -> properties
+        else
+            return null; //new org.simplejta.tm.datasource.SimpleXADataSource(TMID, "need a typeid", url,user, pass);
+    }
+
+    protected boolean startTxBeforeOpen()
+    {
+        return true;
+    }
+}

Added: labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/XAProduct.java
===================================================================
--- labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/XAProduct.java	                        (rev 0)
+++ labs/jbosstm/trunk/qa/tests/product/src/com/arjuna/ats/tools/perftest/product/XAProduct.java	2012-01-05 07:28:03 UTC (rev 37834)
@@ -0,0 +1,97 @@
+package com.arjuna.ats.tools.perftest.product;
+
+import com.arjuna.ats.tools.perftest.DbWrapper;
+
+import javax.transaction.*;
+import javax.transaction.xa.XAResource;
+import javax.transaction.xa.Xid;
+import javax.transaction.xa.XAException;
+import javax.sql.DataSource;
+import javax.sql.XADataSource;
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.util.*;
+
+public class XAProduct extends Product
+{
+    private List<XAResource> resources = new ArrayList<XAResource> ();
+    private List<Xid> xids = new ArrayList<Xid> ();
+
+    public String getName()
+    {
+        return "XA";
+    }
+
+    protected void beginTx() throws SystemException, NotSupportedException, SQLException, XAException
+    {
+        xids.clear();
+
+        for (XAResource res : resources)
+        {
+            Xid xid = DbWrapper.createJJHXid();
+
+            xids.add(xid);
+            res.start(xid, XAResource.TMNOFLAGS);
+        }
+    }
+
+    protected void suspendTx() throws SQLException, XAException, SystemException
+    {
+        for (int i = 0; i < resources.size(); i++)
+            resources.get(i).end(xids.get(i), XAResource.TMSUSPEND);
+    }
+
+    protected void resumeTx() throws SQLException, XAException, SystemException, InvalidTransactionException
+    {
+        for (int i = 0; i < resources.size(); i++)
+            resources.get(i).start(xids.get(i), XAResource.TMRESUME);
+    }
+
+    protected void commitTx(Connection[] connections) throws XAException
+    {
+        for (int i = 0; i < resources.size(); i++)
+        {
+            XAResource res = resources.get(i);
+            Xid xid = xids.get(i);
+
+            res.end(xid, XAResource.TMSUCCESS);
+            res.commit(xid, true);
+        }
+    }
+
+    protected void closeConnection(Connection c) throws SQLException
+    {
+        c.commit();
+        c.close();
+    }
+
+    protected boolean supportsDb(String db)
+    {
+        return DbWrapper.isDerby(db) || DbWrapper.isMysql(db) || DbWrapper.isH2(db);
+    }
+
+    protected DataSource createDataSource(String dsName, final Properties props) throws SQLException
+    {
+        DataSource xads = DbWrapper.createDataSource(dsName, props);
+
+        if (xads != null && xads instanceof XADataSource)
+            resources.add(((XADataSource) xads).getXAConnection().getXAResource());
+
+        return xads;
+    }
+
+    public TransactionManager getTransactionManager()
+    {
+        return new TransactionManager() {
+            public void begin() throws NotSupportedException, SystemException {}
+            public void commit() throws HeuristicMixedException, HeuristicRollbackException, IllegalStateException, RollbackException, SecurityException, SystemException {}
+            public int getStatus() throws SystemException {return 0;}
+            public Transaction getTransaction() throws SystemException {return null;}
+            public void resume(Transaction transaction) throws IllegalStateException, InvalidTransactionException, SystemException {}
+            public void rollback() throws IllegalStateException, SecurityException, SystemException {}
+            public void setRollbackOnly() throws IllegalStateException, SystemException {}
+            public void setTransactionTimeout(int i) throws SystemException {}
+            public Transaction suspend() throws SystemException {return null;}
+        };
+    }
+}



More information about the jboss-svn-commits mailing list