/**
*
* Copyright 2004 Hiram Chirino
*
* Licensed 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.codehaus.activemq.ra;
import org.codehaus.activemq.ActiveMQXASession;
import org.codehaus.activemq.Closeable;
import org.codehaus.activemq.ActiveMQXAConnection;
import org.codehaus.activemq.message.ActiveMQMessage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import javax.jms.IllegalStateException;
import javax.jms.JMSException;
import javax.jms.TransactionInProgressException;
import javax.jms.MessageListener;
import javax.transaction.xa.XAException;
import javax.transaction.xa.Xid;
import javax.resource.spi.endpoint.MessageEndpoint;
import javax.resource.ResourceException;
/**
* The ActiveMQRASession extends the ActiveMQXASession so
* that it is more flexible in terms of using the availble
* transaction context. A normal ActiveMQXASession implements
* the XASession interface stictly which means that it
* can only do work in the context of an XA transaction.
*
* @version $Revision: 1.1.2.1 $
*/
public class ActiveMQRASession extends ActiveMQXASession implements Closeable {
private static final Log log = LogFactory.getLog(ActiveMQRASession.class);
private boolean inLocalTransaction;
private boolean inXATransaction;
private boolean autoCommit=false;
public ActiveMQRASession(ActiveMQXAConnection theConnection, int theAcknowlegeMode) throws JMSException {
super(theConnection, theAcknowlegeMode);
}
public boolean getTransacted() throws JMSException {
return inLocalTransaction || inXATransaction || !autoCommit;
}
protected boolean isXaTransacted() {
return inXATransaction;
}
//////////////////////////////////////////////////////////////////////////
//
// Handle the local transactions
//
//////////////////////////////////////////////////////////////////////////
/**
* @throws JMSException if some internal error occurs
*/
protected void doStartTransaction() throws JMSException {
if( !inXATransaction && !inLocalTransaction && !autoCommit) {
// Start a local transaction.
begin();
}
}
/**
* Used to know when a local transaction has started.
*/
public void begin() throws JMSException {
if( inXATransaction )
throw new TransactionInProgressException("Cannot start local transction. XA transaction is allready in progress.");
if( inLocalTransaction )
throw new TransactionInProgressException("Cannot start local transction. Local transaction is allready in progress.");
inLocalTransaction = true;
startLocalTransaction();
}
public boolean isInLocalTransaction() {
return inLocalTransaction;
}
public void rollback() throws JMSException {
if( inXATransaction )
throw new TransactionInProgressException("Cannot rollback() if an XA transaction is allready in progress ");
if( autoCommit )
throw new javax.jms.IllegalStateException("Not a transacted session");
if( !autoCommit && !inLocalTransaction)
return;
if( !inLocalTransaction )
throw new JMSException("Cannot rollback local transction. Local transaction had not been started.");
inLocalTransaction=false;
rollbackLocalTransaction();
}
public void commit() throws JMSException {
if( inXATransaction )
throw new TransactionInProgressException("Cannot commit() if an XA transaction is allready in progress ");
if( autoCommit )
throw new javax.jms.IllegalStateException("Not a transacted session");
if( !autoCommit && !inLocalTransaction)
return;
if( !inLocalTransaction )
throw new IllegalStateException("Cannot commit local transction. Local transaction had not been started.");
inLocalTransaction=false;
commitLocalTransaction();
}
//////////////////////////////////////////////////////////////////////////
//
// Handle the XA transactions
//
//////////////////////////////////////////////////////////////////////////
public void start(Xid xid, int flags) throws XAException {
if( inLocalTransaction )
throw new XAException(XAException.XAER_PROTO);
super.start(xid, flags);
inXATransaction=true;
}
public void end(Xid xid, int flags) throws XAException {
if( inLocalTransaction )
throw new XAException(XAException.XAER_PROTO);
super.end(xid, flags);
inXATransaction=false;
}
/**
* @return Returns the autoCommit.
*/
public boolean isAutoCommit() {
return autoCommit;
}
/**
* @param autoCommit The autoCommit to set.
*/
public void setAutoCommit(boolean autoCommit) {
this.autoCommit = autoCommit;
}
/**
* Allows you to change the acknowlegeMode of an existing session.
*
* @param acknowledgeMode
*/
public void setAcknowlegeMode(int acknowledgeMode) {
this.acknowledgeMode = acknowledgeMode;
}
protected void preDeliveryHook(MessageListener listener, ActiveMQMessage message) {
if (listener instanceof MessageEndpoint) {
MessageEndpoint endpoint = (MessageEndpoint) listener;
try {
endpoint.beforeDelivery(ActiveMQBaseEndpointWorker.ON_MESSAGE_METHOD);
} catch (NoSuchMethodException e) {
log.error(e.toString(), e);
} catch (ResourceException e) {
log.warn(e.toString(), e);
}
}
}
protected void postDeliveryHook(MessageListener listener, ActiveMQMessage message) {
if (listener instanceof MessageEndpoint) {
MessageEndpoint endpoint = (MessageEndpoint) listener;
try {
endpoint.afterDelivery();
} catch (ResourceException e) {
log.warn(e.toString(), e);
}
}
}
}