/******************************************************************************* * Copyright (c) 2007 - 2014 Red Hat, Inc. * Distributed under license by Red Hat, Inc. All rights reserved. * This program is made available under the terms of the * Eclipse Public License v1.0 which accompanies this distribution, * and is available at http://www.eclipse.org/legal/epl-v10.html * * Contributor: * Red Hat, Inc. - initial API and implementation ******************************************************************************/ package org.hibernate.console; import java.sql.Connection; import java.sql.SQLException; import java.util.ArrayList; import java.util.List; import java.util.Properties; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.InvalidTransactionException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.Status; import javax.transaction.Synchronization; import javax.transaction.SystemException; import javax.transaction.Transaction; import javax.transaction.TransactionManager; import javax.transaction.xa.XAResource; import org.hibernate.HibernateException; import org.hibernate.service.ServiceRegistry; import org.hibernate.service.ServiceRegistryBuilder; import org.hibernate.service.jdbc.connections.spi.ConnectionProvider; import org.hibernate.transaction.TransactionManagerLookup; public class FakeTransactionManagerLookup implements TransactionManagerLookup { public TransactionManager getTransactionManager(Properties props) throws HibernateException { if ( FakeTransactionManager.INSTANCE == null ) { FakeTransactionManager.INSTANCE = new FakeTransactionManager(props); } return FakeTransactionManager.INSTANCE; } public String getUserTransactionName() { return null; //throw new UnsupportedOperationException(); } public Object getTransactionIdentifier(Transaction transaction) { return transaction; } } class FakeTransactionManager implements TransactionManager { public static FakeTransactionManager INSTANCE; private FakeTransaction current; ConnectionProvider connections; public FakeTransactionManager(Properties props) { ServiceRegistryBuilder builder = new ServiceRegistryBuilder(); ServiceRegistry buildServiceRegistry = builder.applySettings(props).buildServiceRegistry(); connections = buildServiceRegistry.getService(ConnectionProvider.class); } public void begin() throws NotSupportedException, SystemException { current = new FakeTransaction(this); current.begin(); } public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { if(current!=null) current.commit(); } public int getStatus() throws SystemException { if(current!=null) { return current.getStatus(); } else { return Status.STATUS_NO_TRANSACTION; } } public Transaction getTransaction() throws SystemException { return current; } public void resume(Transaction tx) throws InvalidTransactionException, IllegalStateException, SystemException { current = (FakeTransaction) tx; } public void rollback() throws IllegalStateException, SecurityException, SystemException { if(current!=null) current.rollback(); } public void setRollbackOnly() throws IllegalStateException, SystemException { if(current!=null) current.setRollbackOnly(); } public void setTransactionTimeout(int t) throws SystemException { } public Transaction suspend() throws SystemException { Transaction result = current; current = null; return result; } public FakeTransaction getCurrent() { return current; } void endCurrent(FakeTransaction tx) { if (current==tx) current=null; } } class FakeTransaction implements Transaction { int status; private Connection connection; List<Synchronization> synchronizations = new ArrayList<Synchronization>(); private FakeTransactionManager transactionManager; FakeTransaction(FakeTransactionManager transactionManager) { status = Status.STATUS_NO_TRANSACTION; this.transactionManager = transactionManager; } public void begin() throws SystemException { try { connection = transactionManager.connections.getConnection(); } catch (SQLException sqle) { sqle.printStackTrace(); throw new SystemException(sqle.toString()); } status = Status.STATUS_ACTIVE; } public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { if (status == Status.STATUS_MARKED_ROLLBACK) { rollback(); } else { status = Status.STATUS_PREPARING; for (Synchronization s : synchronizations) { s.beforeCompletion(); } status = Status.STATUS_COMMITTING; try { connection.commit(); connection.close(); } catch (SQLException sqle) { status = Status.STATUS_UNKNOWN; throw new SystemException(); } status = Status.STATUS_COMMITTED; for (Synchronization s : synchronizations) { s.afterCompletion(status); } //status = Status.STATUS_NO_TRANSACTION; transactionManager.endCurrent(this); } } public boolean delistResource(XAResource arg0, int arg1) throws IllegalStateException, SystemException { // TODO Auto-generated method stub return false; } public boolean enlistResource(XAResource arg0) throws RollbackException, IllegalStateException, SystemException { // TODO Auto-generated method stub return false; } public int getStatus() throws SystemException { return status; } public void registerSynchronization(Synchronization sync) throws RollbackException, IllegalStateException, SystemException { synchronizations.add(sync); } public void rollback() throws IllegalStateException, SystemException { status = Status.STATUS_ROLLING_BACK; // Synch.beforeCompletion() should *not* be called for rollbacks // for ( int i=0; i<synchronizations.size(); i++ ) { // Synchronization s = (Synchronization) synchronizations.get(i); // s.beforeCompletion(); // } status = Status.STATUS_ROLLEDBACK; try { connection.rollback(); connection.close(); } catch (SQLException sqle) { status = Status.STATUS_UNKNOWN; throw new SystemException(); } for (Synchronization s : synchronizations) { s.afterCompletion(status); } //status = Status.STATUS_NO_TRANSACTION; transactionManager.endCurrent(this); } public void setRollbackOnly() throws IllegalStateException, SystemException { status = Status.STATUS_MARKED_ROLLBACK; } void setConnection(Connection connection) { this.connection = connection; } public Connection getConnection() { return connection; } }