/**
*
* Copyright 2004 Protique Ltd
*
* 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.activemq.broker.impl;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import javax.jms.JMSException;
import javax.naming.Context;
import javax.transaction.xa.XAException;
import org.activemq.broker.Broker;
import org.activemq.broker.BrokerAdmin;
import org.activemq.broker.BrokerClient;
import org.activemq.broker.ConsumerInfoListener;
import org.activemq.capacity.DelegateCapacityMonitor;
import org.activemq.io.util.MemoryBoundedObjectManager;
import org.activemq.io.util.MemoryBoundedQueueManager;
import org.activemq.jndi.ReadOnlyContext;
import org.activemq.message.ActiveMQDestination;
import org.activemq.message.ActiveMQMessage;
import org.activemq.message.ActiveMQXid;
import org.activemq.message.ConnectionInfo;
import org.activemq.message.ConsumerInfo;
import org.activemq.message.MessageAck;
import org.activemq.message.ProducerInfo;
import org.activemq.security.SecurityAdapter;
import org.activemq.service.DeadLetterPolicy;
import org.activemq.service.MessageContainerAdmin;
import org.activemq.service.MessageContainerManager;
import org.activemq.service.RedeliveryPolicy;
import org.activemq.service.Transaction;
import org.activemq.service.TransactionManager;
import org.activemq.service.boundedvm.DurableQueueBoundedMessageManager;
import org.activemq.service.boundedvm.TransientQueueBoundedMessageManager;
import org.activemq.service.boundedvm.TransientTopicBoundedMessageManager;
import org.activemq.service.impl.DurableTopicMessageContainerManager;
import org.activemq.store.PersistenceAdapter;
import org.activemq.store.PersistenceAdapterFactory;
import org.activemq.store.TransactionStore;
import org.activemq.store.vm.VMPersistenceAdapter;
import org.activemq.store.vm.VMTransactionManager;
import org.activemq.util.Callback;
import org.activemq.util.ExceptionTemplate;
import org.activemq.util.JMSExceptionHelper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import EDU.oswego.cs.dl.util.concurrent.ConcurrentHashMap;
import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArrayList;
/**
* The default {@link Broker} implementation
*
* @version $Revision: 1.1.1.1 $
*/
public class DefaultBroker extends DelegateCapacityMonitor implements Broker, BrokerAdmin {
private static final Log log = LogFactory.getLog(DefaultBroker.class);
protected static final String PROPERTY_STORE_DIRECTORY = "activemq.store.dir";
protected static final String PERSISTENCE_ADAPTER_FACTORY = "activemq.persistenceAdapterFactory";
protected static final Class[] NEWINSTANCE_PARAMETER_TYPES = {File.class};
private static final long DEFAULT_MAX_MEMORY_USAGE = 20 * 1024 * 1024; //20mb
private PersistenceAdapter persistenceAdapter;
private TransactionManager transactionManager;
private MessageContainerManager[] containerManagers;
private File tempDir;
private MemoryBoundedObjectManager memoryManager;
private MemoryBoundedQueueManager queueManager;
private TransactionStore preparedTransactionStore;
private final String brokerName;
private final String brokerClusterName;
private Map containerManagerMap;
private CopyOnWriteArrayList consumerInfoListeners;
private MessageContainerManager persistentTopicMCM;
private MessageContainerManager transientTopicMCM;
private MessageContainerManager transientQueueMCM;
private DurableQueueBoundedMessageManager persistentQueueMCM;
private SecurityAdapter securityAdapter;
private RedeliveryPolicy redeliveryPolicy;
private DeadLetterPolicy deadLetterPolicy;
private AdvisorySupport advisory;
public DefaultBroker(String brokerName, String brokerClusterName, MemoryBoundedObjectManager memoryManager) {
this.brokerName = brokerName;
this.brokerClusterName = brokerClusterName;
this.memoryManager = memoryManager;
queueManager = new MemoryBoundedQueueManager(memoryManager);
setDelegate(memoryManager);
containerManagerMap = new ConcurrentHashMap();
consumerInfoListeners = new CopyOnWriteArrayList();
this.advisory = new AdvisorySupport(this);
}
public DefaultBroker(String brokerName, MemoryBoundedObjectManager memoryManager) {
this(brokerName, "default", memoryManager);
}
public DefaultBroker(String brokerName, String cluserName) {
this(brokerName, cluserName, new MemoryBoundedObjectManager("Broker Memory Manager", DEFAULT_MAX_MEMORY_USAGE));
}
public DefaultBroker(String brokerName) {
this(brokerName, new MemoryBoundedObjectManager("Broker Memory Manager", DEFAULT_MAX_MEMORY_USAGE));
}
public DefaultBroker(String brokerName, String brokerClusterName, PersistenceAdapter persistenceAdapter) {
this(brokerName, brokerClusterName, new MemoryBoundedObjectManager("Broker Memory Manager", DEFAULT_MAX_MEMORY_USAGE));
this.persistenceAdapter = persistenceAdapter;
}
public DefaultBroker(String brokerName, PersistenceAdapter persistenceAdapter) {
this(brokerName);
this.persistenceAdapter = persistenceAdapter;
}
/**
* Start this Service
*
* @throws JMSException
*/
public void start() throws JMSException {
if (redeliveryPolicy == null) {
redeliveryPolicy = new RedeliveryPolicy();
}
if (deadLetterPolicy == null){
deadLetterPolicy = new DeadLetterPolicy(this);
}
if (persistenceAdapter == null) {
persistenceAdapter = createPersistenceAdapter();
}
persistenceAdapter.start();
if (transactionManager == null) {
preparedTransactionStore = persistenceAdapter.createTransactionStore();
transactionManager = new VMTransactionManager(this, preparedTransactionStore);
}
transactionManager.start();
// force containers to be created
if (containerManagerMap.isEmpty()) {
makeDefaultContainerManagers();
}
getContainerManagers();
for (int i = 0; i < containerManagers.length; i++) {
containerManagers[i].setDeadLetterPolicy(this.deadLetterPolicy);
containerManagers[i].start();
}
}
/**
* stop this Service
*
* @throws JMSException
*/
public void stop() throws JMSException {
ExceptionTemplate template = new ExceptionTemplate();
if (containerManagers != null) {
for (int i = 0; i < containerManagers.length; i++) {
final MessageContainerManager containerManager = containerManagers[i];
template.run(new Callback() {
public void execute() throws Throwable {
containerManager.stop();
}
});
}
}
if (transactionManager != null) {
template.run(new Callback() {
public void execute() throws Throwable {
transactionManager.stop();
}
});
}
template.run(new Callback() {
public void execute() throws Throwable {
persistenceAdapter.stop();
}
});
template.throwJMSException();
}
// Broker interface
//-------------------------------------------------------------------------
public void addClient(BrokerClient client, ConnectionInfo info) throws JMSException {
if (securityAdapter != null) {
securityAdapter.authorizeConnection(client, info);
}
advisory.addConnection(client,info);
}
public void removeClient(BrokerClient client, ConnectionInfo info) throws JMSException {
if (transactionManager != null) {
transactionManager.cleanUpClient(client);
}
advisory.removeConnection(client,info);
}
public void addMessageProducer(BrokerClient client, ProducerInfo info) throws JMSException {
if (securityAdapter != null) {
securityAdapter.authorizeProducer(client, info);
}
advisory.addProducer(client,info);
}
public void removeMessageProducer(BrokerClient client, ProducerInfo info) throws JMSException {
advisory.removeProducer(client,info);
}
/**
* Add an active message consumer
*/
public void addMessageConsumer(BrokerClient client, ConsumerInfo info) throws JMSException {
validateConsumer(info);
if (securityAdapter != null) {
securityAdapter.authorizeConsumer(client, info);
}
advisory.addAdvisory(client, info);
MessageContainerManager[] array = getContainerManagers();
for (int i = 0;i < array.length;i++) {
array[i].addMessageConsumer(client, info);
}
fireConsumerInfo(client, info);
}
/**
* remove an active message consumer
*/
public void removeMessageConsumer(BrokerClient client, ConsumerInfo info) throws JMSException {
validateConsumer(info);
advisory.removeAdvisory(client, info);
for (int i = 0;i < containerManagers.length;i++) {
containerManagers[i].removeMessageConsumer(client, info);
}
fireConsumerInfo(client, info);
}
/**
* send a message to the broker
*/
public void sendMessage(BrokerClient client, ActiveMQMessage message) throws JMSException {
checkValid();
ActiveMQDestination destination = message.getJMSActiveMQDestination();
if (destination == null) {
throw new JMSException("No destination specified for the Message");
}
if (message.getJMSMessageID() == null && !destination.isAdvisory()) {
throw new JMSException("No messageID specified for the Message");
}
associateTransaction(message);
try {
if (destination.isComposite()) {
boolean first = true;
for (Iterator iter = destination.getChildDestinations().iterator();iter.hasNext();) {
ActiveMQDestination childDestination = (ActiveMQDestination) iter.next();
// lets shallow copy just in case
if (first) {
first = false;
}
else {
message = message.shallowCopy();
}
message.setJMSDestination(childDestination);
doMessageSend(client, message);
}
}
else {
if (destination.isTempDestinationAdvisory() && !client.isBrokerConnection()) {
advisory.processTempDestinationAdvisory(client,message);
}
doMessageSend(client, message);
}
}
finally {
disAssociateTransaction();
}
}
/**
* Acknowledge consumption of a message by the Message Consumer
*/
public void acknowledgeMessage(BrokerClient client, MessageAck ack) throws JMSException {
associateTransaction(ack);
try {
for (int i = 0; i < containerManagers.length; i++) {
containerManagers[i].acknowledgeMessage(client, ack);
}
} finally {
disAssociateTransaction();
}
}
public void deleteSubscription(String clientId, String subscriberName) throws JMSException {
for (int i = 0; i < containerManagers.length; i++) {
containerManagers[i].deleteSubscription(clientId, subscriberName);
}
}
/**
* Start a transaction.
*
* @see org.activemq.broker.Broker#startTransaction(org.activemq.broker.BrokerClient, java.lang.String)
*/
public void startTransaction(BrokerClient client, String transactionId) throws JMSException {
transactionManager.createLocalTransaction(client, transactionId);
}
public void commitTransaction(BrokerClient client, String transactionId) throws JMSException {
try {
Transaction transaction = transactionManager.getLocalTransaction(transactionId);
transaction.commit(true);
}
catch (XAException e) {
// TODO: I think the XAException should propagate all the way to the client.
throw (JMSException) new JMSException(e.getMessage()).initCause(e);
}
}
/**
* rollback a transaction
*/
public void rollbackTransaction(BrokerClient client, String transactionId) throws JMSException {
try {
Transaction transaction = transactionManager.getLocalTransaction(transactionId);
transaction.rollback();
}
catch (XAException e) {
// TODO: I think the XAException should propagate all the way to the client.
throw (JMSException) new JMSException(e.getMessage()).initCause(e);
}
}
/**
* Starts an XA Transaction.
*
* @see org.activemq.broker.Broker#startTransaction(org.activemq.broker.BrokerClient, org.activemq.message.ActiveMQXid)
*/
public void startTransaction(BrokerClient client, ActiveMQXid xid) throws XAException {
transactionManager.createXATransaction(client, xid);
}
/**
* Prepares an XA Transaciton.
*
* @see org.activemq.broker.Broker#prepareTransaction(org.activemq.broker.BrokerClient, org.activemq.message.ActiveMQXid)
*/
public int prepareTransaction(BrokerClient client, ActiveMQXid xid) throws XAException {
Transaction transaction = transactionManager.getXATransaction(xid);
return transaction.prepare();
}
/**
* Rollback an XA Transaction.
*
* @see org.activemq.broker.Broker#rollbackTransaction(org.activemq.broker.BrokerClient, org.activemq.message.ActiveMQXid)
*/
public void rollbackTransaction(BrokerClient client, ActiveMQXid xid) throws XAException {
Transaction transaction = transactionManager.getXATransaction(xid);
transaction.rollback();
}
/**
* Commit an XA Transaction.
*
* @see org.activemq.broker.Broker#commitTransaction(org.activemq.broker.BrokerClient, org.activemq.message.ActiveMQXid, boolean)
*/
public void commitTransaction(BrokerClient client, ActiveMQXid xid, boolean onePhase) throws XAException {
Transaction transaction = transactionManager.getXATransaction(xid);
transaction.commit(onePhase);
}
/**
* Gets the prepared XA transactions.
*
* @see org.activemq.broker.Broker#getPreparedTransactions(org.activemq.broker.BrokerClient)
*/
public ActiveMQXid[] getPreparedTransactions(BrokerClient client) throws XAException {
return transactionManager.getPreparedXATransactions();
}
// Properties
//-------------------------------------------------------------------------
/**
* Get a temp directory - used for spooling
*
* @return a File ptr to the directory
*/
public File getTempDir() {
if (tempDir == null) {
String dirName = System.getProperty("activemq.store.tempdir", "ActiveMQTemp");
tempDir = new File(dirName);
}
return tempDir;
}
public String getBrokerName() {
return brokerName;
}
/**
* @return Returns the brokerClusterName.
*/
public String getBrokerClusterName() {
return brokerClusterName;
}
public void setTempDir(File tempDir) {
this.tempDir = tempDir;
}
public MessageContainerManager[] getContainerManagers() {
if (containerManagers == null) {
containerManagers = createContainerManagers();
}
return containerManagers;
}
public Map getContainerManagerMap() {
return containerManagerMap;
}
public void setContainerManagerMap(Map containerManagerMap) {
this.containerManagerMap = containerManagerMap;
this.containerManagers = null;
}
public PersistenceAdapter getPersistenceAdapter() {
return persistenceAdapter;
}
public void setPersistenceAdapter(PersistenceAdapter persistenceAdapter) {
this.persistenceAdapter = persistenceAdapter;
}
public TransactionManager getTransactionManager() {
return transactionManager;
}
public void setTransactionManager(TransactionManager transactionManager) {
this.transactionManager = transactionManager;
}
public SecurityAdapter getSecurityAdapter() {
return securityAdapter;
}
public void setSecurityAdapter(SecurityAdapter securityAdapter) {
this.securityAdapter = securityAdapter;
}
public RedeliveryPolicy getRedeliveryPolicy() {
return redeliveryPolicy;
}
public void setRedeliveryPolicy(RedeliveryPolicy redeliveryPolicy) {
this.redeliveryPolicy = redeliveryPolicy;
}
public TransactionStore getPreparedTransactionStore() {
return preparedTransactionStore;
}
public void setPreparedTransactionStore(TransactionStore preparedTransactionStore) {
this.preparedTransactionStore = preparedTransactionStore;
}
/**
* @return the DeadLetterPolicy
*/
public DeadLetterPolicy getDeadLetterPolicy(){
return deadLetterPolicy;
}
/**
* set the dead letter policy
* @param deadLetterPolicy
*/
public void setDeadLetterPolicy(DeadLetterPolicy deadLetterPolicy){
this.deadLetterPolicy = deadLetterPolicy;
}
/**
* @return Returns the maximumMemoryUsage.
*/
public long getMaximumMemoryUsage() {
return memoryManager.getValueLimit();
}
/**
* @param maximumMemoryUsage The maximumMemoryUsage to set.
*/
public void setMaximumMemoryUsage(long maximumMemoryUsage) {
this.memoryManager.setValueLimit(maximumMemoryUsage);
}
public Context getDestinationContext(Hashtable environment) {
Map data = new ConcurrentHashMap();
for (Iterator iter = containerManagerMap.entrySet().iterator(); iter.hasNext();) {
Map.Entry entry = (Map.Entry) iter.next();
String name = entry.getKey().toString();
MessageContainerManager manager = (MessageContainerManager) entry.getValue();
Context context = new ReadOnlyContext(environment, manager.getDestinations());
data.put(name, context);
}
return new ReadOnlyContext(environment, data);
}
// Implementation methods
//-------------------------------------------------------------------------
protected void doMessageSend(BrokerClient client, ActiveMQMessage message) throws JMSException {
if (securityAdapter != null) {
securityAdapter.authorizeSendMessage(client, message);
}
ActiveMQDestination dest = message.getJMSActiveMQDestination();
if (dest.isTopic()){
if (message.isPersistent() && !dest.isTemporary()){
persistentTopicMCM.sendMessage(client,message);
}
transientTopicMCM.sendMessage(client, message);
}else {
transientQueueMCM.sendMessage(client, message);
persistentQueueMCM.sendMessage(client, message);
}
}
/**
* Factory method to create a default persistence adapter
*
* @return
*/
protected PersistenceAdapter createPersistenceAdapter() throws JMSException {
File directory = new File(getStoreDirectory());
// lets use reflection to avoid runtime dependency on persistence libraries
PersistenceAdapter answer = null;
String property = System.getProperty(PERSISTENCE_ADAPTER_FACTORY);
if (property != null) {
answer = tryCreatePersistenceAdapter(property, directory, false);
}
if (answer == null) {
answer = tryCreatePersistenceAdapter("org.activemq.broker.impl.DefaultPersistenceAdapterFactory", directory, true);
}
if (answer != null) {
return answer;
}
else {
log.warn("Default message store (journal+derby) could not be found in the classpath or property '" + PERSISTENCE_ADAPTER_FACTORY
+ "' not specified so defaulting to use RAM based message persistence");
return new VMPersistenceAdapter();
}
}
protected PersistenceAdapter tryCreatePersistenceAdapter(String className, File directory, boolean ignoreErrors) throws JMSException {
Class adapterClass = loadClass(className, ignoreErrors);
if (adapterClass != null) {
try {
PersistenceAdapterFactory factory = (PersistenceAdapterFactory) adapterClass.newInstance();
PersistenceAdapter answer = factory.createPersistenceAdapter(directory, memoryManager);
log.info("Persistence adapter created using: " + className);
return answer;
}
catch (IOException cause) {
throw createInstantiateAdapterException(className, (Exception) cause);
}
catch (Throwable e) {
if (!ignoreErrors) {
throw createInstantiateAdapterException(className, e);
}
}
}
return null;
}
protected JMSException createInstantiateAdapterException(String className, Throwable e) {
return JMSExceptionHelper.newJMSException("Persistence adapter could not be created using: "
+ className + ". Reason: " + e, e);
}
/**
* Tries to load the given class from the current context class loader or
* class loader which loaded us or return null if the class could not be found
*/
protected Class loadClass(String name, boolean ignoreErrors) throws JMSException {
try {
return Thread.currentThread().getContextClassLoader().loadClass(name);
}
catch (ClassNotFoundException e) {
try {
return getClass().getClassLoader().loadClass(name);
}
catch (ClassNotFoundException e2) {
if (ignoreErrors) {
log.trace("Could not find class: " + name + " on the classpath");
return null;
}
else {
throw JMSExceptionHelper.newJMSException("Could not find class: " + name + " on the classpath. Reason: " + e, e);
}
}
}
}
protected String getStoreDirectory() {
return System.getProperty(PROPERTY_STORE_DIRECTORY, "ActiveMQ");
}
/**
* Factory method to create the default container managers
*
* @return
*/
protected MessageContainerManager[] createContainerManagers() {
int size = containerManagerMap.size();
MessageContainerManager[] answer = new MessageContainerManager[size];
containerManagerMap.values().toArray(answer);
return answer;
}
protected void makeDefaultContainerManagers() {
transientTopicMCM = new TransientTopicBoundedMessageManager(queueManager);
containerManagerMap.put("transientTopicContainer", transientTopicMCM);
persistentTopicMCM = new DurableTopicMessageContainerManager(persistenceAdapter, redeliveryPolicy, deadLetterPolicy);
containerManagerMap.put("persistentTopicContainer", persistentTopicMCM);
persistentQueueMCM = new DurableQueueBoundedMessageManager(persistenceAdapter, queueManager, redeliveryPolicy, deadLetterPolicy);
containerManagerMap.put("persistentQueueContainer", persistentQueueMCM);
transientQueueMCM = new TransientQueueBoundedMessageManager(queueManager,redeliveryPolicy, deadLetterPolicy);
containerManagerMap.put("transientQueueContainer", transientQueueMCM);
}
/**
* Ensures the consumer is valid, throwing a meaningful exception if not
*
* @param info
* @throws JMSException
*/
protected void validateConsumer(ConsumerInfo info) throws JMSException {
if (info.getConsumerId() == null) {
throw new JMSException("No consumerId specified for the ConsumerInfo");
}
}
protected void checkValid() throws JMSException {
if (containerManagers == null) {
throw new JMSException("This Broker has not yet been started. Ensure start() is called before invoking action methods");
}
}
/**
* Add a ConsumerInfoListener to the Broker
*
* @param l
*/
public void addConsumerInfoListener(ConsumerInfoListener l) {
consumerInfoListeners.add(l);
}
/**
* Remove a ConsumerInfoListener from the Broker
*
* @param l
*/
public void removeConsumerInfoListener(ConsumerInfoListener l) {
consumerInfoListeners.remove(l);
}
protected void fireConsumerInfo(BrokerClient client, ConsumerInfo info) {
for (Iterator i = consumerInfoListeners.iterator(); i.hasNext();) {
ConsumerInfoListener l = (ConsumerInfoListener) i.next();
l.onConsumerInfo(client, info);
}
}
/**
* @return the MessageContainerManager for durable topics
*/
public MessageContainerManager getPersistentTopicContainerManager() {
return persistentTopicMCM;
}
/**
* @return the MessageContainerManager for transient topics
*/
public MessageContainerManager getTransientTopicContainerManager() {
return transientTopicMCM;
}
/**
* @return the MessageContainerManager for persistent queues
*/
public MessageContainerManager getPersistentQueueContainerManager() {
return persistentQueueMCM;
}
/**
* @return the MessageContainerManager for transient queues
*/
public MessageContainerManager getTransientQueueContainerManager() {
return transientQueueMCM;
}
/**
* @see org.activemq.broker.Broker#getBrokerAdmin()
*/
public BrokerAdmin getBrokerAdmin() {
return this;
}
public void createMessageContainer(ActiveMQDestination dest) throws JMSException {
for (int i = 0; i < containerManagers.length; i++) {
containerManagers[i].createMessageContainer(dest);
}
}
public void destoryMessageContainer(ActiveMQDestination dest) throws JMSException {
for (int i = 0; i < containerManagers.length; i++) {
containerManagers[i].destroyMessageContainer(dest);
}
}
public MessageContainerAdmin getMessageContainerAdmin(ActiveMQDestination dest) throws JMSException {
for (int i = 0; i < containerManagers.length; i++) {
Map messageContainerAdmins = containerManagers[i].getMessageContainerAdmins();
MessageContainerAdmin mca = (MessageContainerAdmin) messageContainerAdmins.get(dest);
if( mca != null ) {
return mca;
}
}
return null;
}
/**
* @throws JMSException
* @see org.activemq.broker.BrokerAdmin#listDestinations()
*/
public MessageContainerAdmin[] listMessageContainerAdmin() throws JMSException {
ArrayList l = new ArrayList();
for (int i = 0; i < containerManagers.length; i++) {
Map messageContainerAdmins = containerManagers[i].getMessageContainerAdmins();
for (Iterator iter = messageContainerAdmins.values().iterator(); iter.hasNext();) {
MessageContainerAdmin mca = (MessageContainerAdmin) iter.next();
l.add(mca);
}
}
MessageContainerAdmin answer[] = new MessageContainerAdmin[l.size()];
l.toArray(answer);
return answer;
}
/**
* Add a message to a dead letter queue
* @param deadLetterName
* @param message
* @throws JMSException
*/
public void sendToDeadLetterQueue(String deadLetterName,ActiveMQMessage message) throws JMSException{
if (persistentQueueMCM != null){
persistentQueueMCM.sendToDeadLetterQueue(deadLetterName, message);
log.debug(message + " sent to DLQ: " + deadLetterName);
}
}
/**
* send a message to the broker within a transaction
public void sendTransactedMessage(final BrokerClient client, final String transactionId, final ActiveMQMessage message) throws JMSException {
getTransactionFor(message).addPostCommitTask(new SendMessageTransactionTask(client, message));
}
*/
/**
* Acknowledge consumption of a message within a transaction
public void acknowledgeTransactedMessage(final BrokerClient client, final String transactionId, final MessageAck ack) throws JMSException {
Transaction transaction;
if (ack.isXaTransacted()) {
try {
transaction = transactionManager.getXATransaction(new ActiveMQXid(transactionId));
}
catch (XAException e) {
throw (JMSException) new JMSException(e.getMessage()).initCause(e);
}
}
else {
transaction = transactionManager.getLocalTransaction(transactionId);
}
transaction.addPostCommitTask(new MessageAckTransactionTask(client, ack));
transaction.addPostRollbackTask(new RedeliverMessageTransactionTask(client, ack));
// we need to tell the dispatcher that we can now accept another message
// even though we don't really ack the message until the commit
// this is because if we have a prefetch value of 1, we can never consume 2 messages
// in a transaction, since the ack for the first message never arrives until the commit
for (int i = 0; i < containerManagers.length; i++) {
containerManagers[i].acknowledgeTransactedMessage(client, transactionId, ack);
}
}
*/
/**
* @param message
* @return
* @throws JMSException
private Transaction getTransactionFor(ActiveMQMessage message) throws JMSException {
String transactionId = message.getTransactionId();
if (message.isXaTransacted()) {
try {
return transactionManager.getXATransaction(new ActiveMQXid(transactionId));
}
catch (XAException e) {
throw (JMSException) new JMSException(e.getMessage()).initCause(e);
}
}
return transactionManager.getLocalTransaction(transactionId);
}
public void acknowledgeMessageRecover(MessageAck ack) {
}
public void sendMessageRecover(ActiveMQMessage message) throws JMSException {
}
*/
/**
* Associates a Transaction with the current thread. Once this call is finished,
* the Transactio ncan be obtained via TransactionManager.getContexTransaction().
* @param message
* @throws JMSException
*/
private final void associateTransaction(ActiveMQMessage message) throws JMSException {
Transaction transaction;
if( message.isPartOfTransaction() ) {
if (message.isXaTransacted()) {
try {
transaction = transactionManager.getXATransaction((ActiveMQXid) message.getTransactionId());
}
catch (XAException e) {
throw (JMSException) new JMSException(e.getMessage()).initCause(e);
}
} else {
transaction = transactionManager.getLocalTransaction((String) message.getTransactionId());
}
} else {
transaction = null;
}
TransactionManager.setContexTransaction(transaction);
}
private void disAssociateTransaction() {
TransactionManager.setContexTransaction(null);
}
/**
* Associates a Transaction with the current thread. Once this call is finished,
* the Transactio ncan be obtained via TransactionManager.getContexTransaction().
* @param ack
* @throws JMSException
*/
private void associateTransaction(MessageAck ack) throws JMSException {
Transaction transaction;
if( ack.isPartOfTransaction() ) {
if (ack.isXaTransacted()) {
try {
transaction = transactionManager.getXATransaction((ActiveMQXid) ack.getTransactionId());
}
catch (XAException e) {
throw (JMSException) new JMSException(e.getMessage()).initCause(e);
}
} else {
transaction = transactionManager.getLocalTransaction((String) ack.getTransactionId());
}
} else {
transaction = null;
}
TransactionManager.setContexTransaction(transaction);
}
/**
* @return Returns the memoryManager.
*/
public MemoryBoundedObjectManager getMemoryManager() {
return memoryManager;
}
/**
* @return Returns the queueManager.
*/
public MemoryBoundedQueueManager getQueueManager() {
return queueManager;
}
}