/*
* JBoss, Home of Professional Open Source.
* Copyright 2008, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags. See the copyright.txt file in the
* distribution for a full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY 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 along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.test.jca.adapter;
import javax.sql.XADataSource;
import javax.sql.XAConnection;
import javax.sql.ConnectionEventListener;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;
import org.omg.PortableInterceptor.HOLDING;
import java.util.Map;
import java.util.HashMap;
import java.util.Arrays;
import java.io.PrintWriter;
import java.sql.SQLException;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLWarning;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.lang.reflect.Proxy;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
/**
* @author <a href="mailto:alex@jboss.org">Alexey Loubyansky</a>
* @version <tt>$Revision: 81036 $</tt>
*/
public class MockedXADataSource
implements XADataSource
{
private static final Map instances = new HashMap();
public static MockedXADataSource getInstance(String url)
{
return (MockedXADataSource)instances.get(url);
}
public static void stop(String url)
{
getInstance(url).stopped = true;
}
public static void start(String url)
{
getInstance(url).stopped = false;
}
public static String[] getUrls()
{
return (String[])instances.keySet().toArray(new String[instances.size()]);
}
private String url;
private boolean stopped;
private int loginTimeout;
private PrintWriter logWriter;
public String getURL()
{
return url;
}
public void setURL(String url)
{
this.url = url;
instances.put(url, this);
}
public int getLoginTimeout() throws SQLException
{
return loginTimeout;
}
public void setLoginTimeout(int seconds) throws SQLException
{
this.loginTimeout = seconds;
}
public PrintWriter getLogWriter() throws SQLException
{
return logWriter;
}
public void setLogWriter(PrintWriter out) throws SQLException
{
this.logWriter = out;
}
public XAConnection getXAConnection() throws SQLException
{
return (XAConnection) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { XAConnection.class }, new MockedXAConnection());
}
public XAConnection getXAConnection(String user, String password) throws SQLException
{
return getXAConnection();
}
// Inner
public class MockedXAConnection implements InvocationHandler
{
private boolean closed;
private Connection con;
private XAResource xaResource = new MockedXAResource();
public MockedXAConnection()
{
con = (Connection) Proxy.newProxyInstance(getClass().getClassLoader(), new Class[] { Connection.class }, new MockedConnection());
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
String name = method.getName();
if ("getXAResource".equals(name))
return xaResource;
if ("getConnection".equals(name))
return con;
if ("close".equals(name))
closed = true;
return null;
}
class MockedConnection implements InvocationHandler
{
private int holdability;
private int txIsolation;
private boolean autoCommit;
private boolean readOnly;
private String catalog;
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
String name = method.getName();
if ("getUrl".equals(name))
return url;
check();
if ("getHoldability".equals(name))
return holdability;
if ("setHoldability".equals(name))
holdability = (Integer) args[0];
if ("getTransactionIsolation".equals(name))
return txIsolation;
if ("setTransactionIsolation".equals(name))
txIsolation = (Integer) args[0];
if ("getAutoCommit".equals(name))
return autoCommit;
if ("setAutoCommit".equals(name))
autoCommit = (Boolean) args[0];
if ("isClosed".equals(name))
return closed;
if ("isReadOnly".equals(name))
return readOnly;
if ("setReadOnly".equals(name))
readOnly = (Boolean) args[0];
if ("close".equals(name))
closed = true;
if ("getCatalog".equals(name))
return catalog;
if ("setCatalog".equals(name))
catalog = (String) args[0];
if ("getMetaData".equals(name))
return getMetaData();
if ("createStatement".equals(name))
return createStatement();
return null;
}
public DatabaseMetaData getMetaData() throws SQLException
{
check();
return (DatabaseMetaData)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{DatabaseMetaData.class},
new InvocationHandler()
{
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
if("getURL".equals(method.getName()))
{
return url;
}
return new UnsupportedOperationException(
"Not implemented: method=" +
method.getName() +
", args=" +
(args == null ? (Object)"null" : Arrays.asList(args))
);
}
}
);
}
public Statement createStatement() throws SQLException
{
check();
return (Statement)Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
new Class[]{Statement.class},
new InvocationHandler()
{
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
String methodName = method.getName();
if("execute".equals(methodName))
{
// let's suppose it went well!
return Boolean.FALSE;
}
return new UnsupportedOperationException(
"Not implemented: method=" +
methodName +
", args=" +
(args == null ? (Object)"null" : Arrays.asList(args))
);
}
}
);
}
// Private
private void check() throws SQLException
{
if(stopped)
{
throw new SQLException("The database is not available: " + url);
}
}
}
}
class MockedXAResource
implements XAResource
{
private int txTimeOut;
public int getTransactionTimeout() throws XAException
{
return txTimeOut;
}
public boolean setTransactionTimeout(int i) throws XAException
{
this.txTimeOut = i;
return true;
}
public boolean isSameRM(XAResource xaResource) throws XAException
{
return xaResource instanceof MockedXAResource;
}
public Xid[] recover(int i) throws XAException
{
throw new UnsupportedOperationException("recover is not implemented.");
}
public int prepare(Xid xid) throws XAException
{
return XAResource.XA_OK;
}
public void forget(Xid xid) throws XAException
{
}
public void rollback(Xid xid) throws XAException
{
}
public void end(Xid xid, int i) throws XAException
{
}
public void start(Xid xid, int i) throws XAException
{
}
public void commit(Xid xid, boolean b) throws XAException
{
}
}
}