/**
*
* 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.codehaus.activemq.transport;
import javax.jms.Destination;
import javax.jms.JMSException;
import javax.jms.Message;
import javax.jms.MessageConsumer;
import javax.jms.MessageListener;
import javax.jms.Session;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.codehaus.activemq.ActiveMQMessageProducer;
import org.codehaus.activemq.message.ActiveMQDestination;
import org.codehaus.activemq.message.ActiveMQMessage;
import org.codehaus.activemq.service.Service;
import EDU.oswego.cs.dl.util.concurrent.SynchronizedInt;
/**
* A NetworkMessageBridge consumes messages from a remote broker and daisy chains them to the local message producer,
* which will pass them into the local broker for consumption
*
* @version $Revision: 1.5 $
*/
class NetworkMessageBridge implements Service, MessageListener {
private String localBrokerName;
private ActiveMQMessageProducer localProducer;
private MessageConsumer remoteConsumer;
private Session localSession;
private Session remoteSession;
private boolean stopped;
private boolean durableTopic;
private ActiveMQDestination destination;
private SynchronizedInt referenceCount;
private static final Log log = LogFactory.getLog(NetworkMessageBridge.class);
/**
* Construct the NetworkMessageConsumer
*/
public NetworkMessageBridge() {
this.referenceCount = new SynchronizedInt(0);
}
/**
* sett the durable value of the consumer
*
* @param durableTopic
*/
public void setDurableTopic(boolean durableTopic) {
this.durableTopic = durableTopic;
}
/**
* @return true if a durable consumer
*/
public boolean isDurableTopic() {
return this.durableTopic;
}
/**
* @return Returns the destination.
*/
public ActiveMQDestination getDestination() {
return destination;
}
/**
* @param destination The destination to set.
*/
public void setDestination(ActiveMQDestination destination) {
this.destination = destination;
}
/**
* @return Returns the localBrokerName.
*/
public String getLocalBrokerName() {
return localBrokerName;
}
/**
* @param localBrokerName The localBrokerName to set.
*/
public void setLocalBrokerName(String localBrokerName) {
this.localBrokerName = localBrokerName;
}
/**
* @return Returns the localSession.
*/
public Session getLocalSession() {
return localSession;
}
/**
* @param localSession The localSession to set.
*/
public void setLocalSession(Session localSession) {
this.localSession = localSession;
}
/**
* @return Returns the remoteSession.
*/
public Session getRemoteSession() {
return remoteSession;
}
/**
* @param remoteSession The remoteSession to set.
*/
public void setRemoteSession(Session remoteSession) {
this.remoteSession = remoteSession;
}
/**
* increment number of references to this consumer
*
* @return the number of references
*/
public int incrementReferenceCount() {
return referenceCount.increment();
}
/**
* decrement number of references to this consumer
*
* @return the number of references
*/
public int decrementReferenceCount() {
return referenceCount.decrement();
}
/**
* start the bridge
*
* @throws JMSException
*/
public void start() throws JMSException {
localProducer = (ActiveMQMessageProducer) localSession.createProducer(null);
localProducer.setReuseMessageId(true);
createRemoteConsumer();
}
private void createRemoteConsumer() throws JMSException {
if (isDurableTopic()) {
String subsName = destination.toString() + "@" + localBrokerName;
remoteConsumer = remoteSession.createDurableSubscriber((javax.jms.Topic) destination, subsName);
}
else {
remoteConsumer = remoteSession.createConsumer(destination);
}
remoteConsumer.setMessageListener(NetworkMessageBridge.this);
}
/**
* stop the bridge
*/
public void stop() {
if (!stopped) {
stopped = true;
referenceCount.set(0);
try {
localSession.close();
remoteSession.close();
}
catch (JMSException jmsEx) {
log.warn("failure in stopping the message bridge", jmsEx);
}
}
}
/**
* Upgrade the remote consumer from a non-durable consumer to a durable consumer
*/
public void upgrade() throws JMSException {
try {
remoteConsumer.close();
} catch (JMSException e) {
log.warn("Failure in stopping the remote session for the message bridge", e);
}
durableTopic = true;
createRemoteConsumer();
}
/**
* @param msg consumed message from remote broker
*/
public void onMessage(Message msg) {
try {
if (!stopped) {
ActiveMQMessage message = (ActiveMQMessage) msg;
if (message != null) {
message = message.shallowCopy();
message.addBrokerVisited(localBrokerName);
Destination destination = message.getJMSDestination();
int deliveryMode = message.getJMSDeliveryMode();
int priority = message.getJMSPriority();
long timeToLive = message.getJMSExpiration() - msg.getJMSTimestamp();
localProducer.send(destination, message, deliveryMode, priority, timeToLive);
//acknowledge the original
msg.acknowledge();
}
}
}
catch (JMSException jmsEx) {
if (!stopped){
log.error("NetworkMessageConsumer failed", jmsEx);
stop();
}
}
}
/**
* @return hash code for this object
*/
public int hashCode() {
return destination.hashCode();
}
/**
* @param obj
* @return true if the obj and this are equal
*/
public boolean equals(Object obj) {
boolean result = false;
if (obj != null && obj instanceof NetworkMessageBridge) {
NetworkMessageBridge other = (NetworkMessageBridge) obj;
result = this.destination.equals(other.destination) && this.isDurableTopic() == other.isDurableTopic();
}
return result;
}
}