/*
* Licensed to the Apache Software Foundation (ASF) under one or more contributor license
* agreements. See the NOTICE file distributed with this work for additional information regarding
* copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License. You may obtain a
* copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License
* is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
* or implied. See the License for the specific language governing permissions and limitations under
* the License.
*/
package org.apache.geode.internal.ra.spi;
import javax.resource.ResourceException;
import javax.resource.spi.LocalTransaction;
import javax.resource.spi.LocalTransactionException;
import javax.transaction.SystemException;
import javax.transaction.TransactionManager;
import org.apache.geode.LogWriter;
import org.apache.geode.cache.CacheFactory;
import org.apache.geode.cache.TransactionId;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.cache.TXStateProxy;
import org.apache.geode.internal.cache.TXManagerImpl;
import org.apache.geode.internal.i18n.LocalizedStrings;
/**
*
*
*/
public class JCALocalTransaction implements LocalTransaction {
private volatile GemFireCacheImpl cache;
private volatile TXManagerImpl gfTxMgr;
private volatile TransactionId tid;
private static final boolean DEBUG = false;
private volatile boolean initDone = false;
JCALocalTransaction(GemFireCacheImpl cache, TXManagerImpl tm) {
this.cache = cache;
this.gfTxMgr = tm;
this.initDone = true;
// System.out.println("Asif:JCALocalTransaction:Param contrcutr for tx ="+
// this );
}
JCALocalTransaction() {
this.cache = null;
this.gfTxMgr = null;
this.initDone = false;
// System.out.println("Asif:JCALocalTransaction:Empty constructor for tx ="+
// this );
}
public void begin() throws ResourceException {
if (DEBUG) {
try {
throw new NullPointerException("Asif:JCALocalTransaction:begin");
} catch (NullPointerException npe) {
npe.printStackTrace();
}
}
try {
if (!initDone || this.cache.isClosed()) {
this.init();
}
// System.out.println("JCALocalTransaction:Asif: cache is ="+cache +
// " for tx ="+this);
LogWriter logger = cache.getLogger();
if (logger.fineEnabled()) {
logger.fine("JCALocalTransaction::begin:");
}
TransactionManager tm = cache.getJTATransactionManager();
if (this.tid != null) {
throw new LocalTransactionException(" A transaction is already in progress");
}
if (tm != null && tm.getTransaction() != null) {
if (logger.fineEnabled()) {
logger.fine("JCAManagedConnection: JTA transaction is on");
}
// This is having a JTA transaction. Assuming ignore jta flag is true,
// explicitly being a gemfire transaction.
TXStateProxy tsp = this.gfTxMgr.getTXState();
if (tsp == null) {
this.gfTxMgr.begin();
tsp = this.gfTxMgr.getTXState();
tsp.setJCATransaction();
this.tid = tsp.getTransactionId();
if (logger.fineEnabled()) {
logger.fine("JCALocalTransaction:begun GFE transaction");
}
} else {
throw new LocalTransactionException("GemFire is already associated with a transaction");
}
} else {
if (logger.fineEnabled()) {
logger.fine("JCAManagedConnection: JTA Transaction does not exist.");
}
}
} catch (SystemException e) {
// this.onError();
throw new ResourceException(e);
}
// Not to be invoked for local transactions managed by the container
// Iterator<ConnectionEventListener> itr = this.listeners.iterator();
// ConnectionEvent ce = new ConnectionEvent(this,
// ConnectionEvent.LOCAL_TRANSACTION_STARTED);
// while (itr.hasNext()) {
// itr.next().localTransactionStarted(ce);
// }
}
public void commit() throws ResourceException {
if (DEBUG) {
try {
throw new NullPointerException("Asif:JCALocalTransaction:commit");
} catch (NullPointerException npe) {
npe.printStackTrace();
}
}
LogWriter logger = cache.getLogger();
if (logger.fineEnabled()) {
logger.fine("JCALocalTransaction:invoked commit");
}
TXStateProxy tsp = this.gfTxMgr.getTXState();
if (tsp != null && this.tid != tsp.getTransactionId()) {
throw new IllegalStateException("Local Transaction associated with Tid = " + this.tid
+ " attempting to commit a different transaction");
}
try {
this.gfTxMgr.commit();
this.tid = null;
} catch (Exception e) {
throw new LocalTransactionException(e.toString());
}
// Iterator<ConnectionEventListener> itr = this.listeners.iterator();
// ConnectionEvent ce = new
// ConnectionEvent(this,ConnectionEvent.LOCAL_TRANSACTION_COMMITTED);
// while( itr.hasNext()) {
// itr.next().localTransactionCommitted(ce);
// }
}
public void rollback() throws ResourceException {
if (DEBUG) {
try {
throw new NullPointerException("Asif:JJCALocalTransaction:rollback");
} catch (NullPointerException npe) {
npe.printStackTrace();
}
}
TXStateProxy tsp = this.gfTxMgr.getTXState();
if (tsp != null && this.tid != tsp.getTransactionId()) {
throw new IllegalStateException("Local Transaction associated with Tid = " + this.tid
+ " attempting to commit a different transaction");
}
LogWriter logger = cache.getLogger();
if (logger.fineEnabled()) {
logger.fine("JCALocalTransaction:invoked rollback");
}
try {
this.gfTxMgr.rollback();
} catch (IllegalStateException ise) {
// It is possible that the GFE transaction has already been rolled back.
if (ise.getMessage()
.equals(LocalizedStrings.TXManagerImpl_THREAD_DOES_NOT_HAVE_AN_ACTIVE_TRANSACTION
.toLocalizedString())) {
// /ignore;
} else {
throw new ResourceException(ise);
}
} catch (Exception e) {
throw new ResourceException(e);
} finally {
this.tid = null;
}
// Iterator<ConnectionEventListener> itr = this.listeners.iterator();
// ConnectionEvent ce = new ConnectionEvent(this,
// ConnectionEvent.LOCAL_TRANSACTION_ROLLEDBACK);
// while (itr.hasNext()) {
// itr.next().localTransactionRolledback(ce);
// }
}
private void init() throws SystemException {
this.cache = (GemFireCacheImpl) CacheFactory.getAnyInstance();
LogWriter logger = this.cache.getLogger();
if (logger.fineEnabled()) {
logger.fine("JCAManagedConnection:init. Inside init");
}
gfTxMgr = cache.getTxManager();
this.initDone = true;
}
boolean transactionInProgress() {
return this.tid != null;
}
}