package org.mom4j.messaging;
import javax.jms.InvalidDestinationException;
import javax.jms.InvalidSelectorException;
import javax.jms.JMSException;
import javax.jms.Message;
import java.io.IOException;
import java.util.*;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.mom4j.api.Mom4jConfig;
import org.mom4j.api.Mom4jConsole;
import org.mom4j.api.Mom4jDestination;
import org.mom4j.messaging.select.Element;
import org.mom4j.messaging.select.Query;
public class Console implements ConsoleMBean, Mom4jConsole {
/** logger */
private static Log log = LogFactory.getLog(Console.class);
private static final String[] STRING_ARRAY = new String[0];
private MessagingServer server;
private DurableSubscriptions durSubs;
private Map queues;
private Map topics;
private Filter pubSub;
private Filter p2p;
Console(MessagingServer server, Mom4jConfig config)
throws javax.jms.JMSException
{
if(server == null) {
throw new IllegalArgumentException("'server' must not be null!");
}
if(config == null) {
throw new IllegalArgumentException("'config' must not be null!");
}
this.server = server;
this.durSubs = new DurableSubscriptions(config.getDurablesStore());
this.queues = Collections.synchronizedMap(new HashMap());
this.topics = Collections.synchronizedMap(new HashMap());
this.pubSub = new PubSubFilter(this);
this.p2p = new P2PFilter(this);
List dest = config.getDestinations();
for(Iterator it = dest.iterator(); it.hasNext();) {
Mom4jDestination d = (Mom4jDestination)it.next();
if(d.getType() == Mom4jDestination.QUEUE) {
this.createQueue(d.getName());
} else {
this.createTopic(d.getName());
}
}
Iterator it = this.durSubs.getSubscriptions();
while(it.hasNext()) {
DurableSubscriptions.Subscription s =
(DurableSubscriptions.Subscription)it.next();
this.register(s.destination, s.consumerId, s.selector);
}
Runtime.getRuntime().addShutdownHook(new Shutdown());
}
public void createQueue(String name)
throws JMSException
{
if(this.queues.get(name) != null) {
throw new JMSException(name + " already exists");
}
org.mom4j.jms.QueueImpl q = new org.mom4j.jms.QueueImpl(name);
this.queues.put(name, Collections.synchronizedMap(new HashMap()));
if(!name.startsWith("tmp")) {
this.server.export(name, q);
}
}
public boolean hasQueue(String name) {
return this.queues.get(name) != null;
}
public void createTopic(String name)
throws JMSException
{
if(this.topics.get(name) != null) {
throw new JMSException(name + " already exists");
}
org.mom4j.jms.TopicImpl t = new org.mom4j.jms.TopicImpl(name);
this.topics.put(name, Collections.synchronizedMap(new HashMap()));
if(!name.startsWith("tmp")) {
this.server.export(name, t);
}
}
public boolean hasTopic(String name) {
return this.topics.get(name) != null;
}
public Collection showQueues() {
ArrayList al = new ArrayList();
Iterator it = this.queues.keySet().iterator();
while(it.hasNext()) {
String name = (String)it.next();
Map map = (Map)this.queues.get(name);
al.add(name + ": " + map.size() + " receivers");
}
return al;
}
public Collection showTopics() {
ArrayList al = new ArrayList();
Iterator it = this.topics.keySet().iterator();
while(it.hasNext()) {
String name = (String)it.next();
Map map = (Map)this.topics.get(name);
al.add(name + ": " + map.size() + " subscribers");
}
return al;
}
public void register(String destination,
String consumerId,
String messageSelector)
throws JMSException
{
Map map = (Map)this.queues.get(destination);
if(map == null) {
map = (Map)this.topics.get(destination);
if(map == null) {
String s = "destination '" + destination + "' unknown";
throw new InvalidDestinationException(s);
}
}
if(map.get(consumerId) != null) {
String s = "consumer '" + consumerId + "' already registered " +
"for destination '" + destination + "'";
throw new JMSException(s);
}
Element root = Element.NULL;
if(messageSelector != null) {
try {
root = Query.parse(messageSelector);
} catch(java.text.ParseException ex) {
log.error("invalid Query: " + messageSelector, ex);
throw new InvalidSelectorException(ex.getMessage());
}
}
map.put(consumerId, root);
}
public String registerDur(String destination,
String subscriberName,
String consumerId,
String messageSelector)
throws JMSException
{
String cid = null;
try {
cid = this.durSubs.getConsumerId(subscriberName);
} catch(IOException ex) {
throw new JMSException(ex.toString());
}
if(cid == null) {
cid = consumerId;
try {
this.durSubs.setSubscription(destination,
subscriberName,
consumerId,
messageSelector);
} catch(IOException ex) {
throw new JMSException(ex.toString());
}
this.register(destination, cid, messageSelector);
}
return cid;
}
public void unregister(String destination, String consumerId)
throws JMSException
{
Map map = (Map)this.queues.get(destination);
if(map == null) {
map = (Map)this.topics.get(destination);
if(map == null) {
String s = "destination '" + destination + "' unknown";
throw new InvalidDestinationException(s);
}
}
map.remove(consumerId);
}
public void unregisterDur(String subscriberName)
throws JMSException
{
DurableSubscriptions.Subscription s = null;
try {
s = (DurableSubscriptions.Subscription)
this.durSubs.getSubscription(subscriberName);
} catch(IOException ex) {
throw new JMSException(ex.toString());
}
this.unregister(s.destination, s.consumerId);
try {
this.durSubs.removeSubscription(subscriberName);
} catch(java.io.IOException ex) {
log.error("error in unregisterDur", ex);
throw new JMSException(ex.getMessage());
}
}
String[] getConsumerIds(String destination)
throws JMSException
{
Map map = (Map)this.queues.get(destination);
if(map == null) {
map = (Map)this.topics.get(destination);
if(map == null) {
String s = "destination '" + destination + "' unknown";
throw new InvalidDestinationException(s);
}
}
return (String[])map.keySet().toArray(STRING_ARRAY);
}
Element getMessageSelector(String destination, String consumerId)
throws JMSException
{
Map map = (Map)this.queues.get(destination);
if(map == null) {
map = (Map)this.topics.get(destination);
if(map == null) {
String s = "destination '" + destination + "' unknown";
throw new InvalidDestinationException(s);
}
}
Element e = (Element)map.get(consumerId);
if(e == null) {
throw new JMSException("unknown consumer '" + consumerId + "'");
}
if(e == Element.NULL) {
return null;
}
return e;
}
public void send(String sessionId,
String destination,
Message msg)
throws IOException,
JMSException
{
this.send(sessionId, destination, msg, true);
}
void send(String sessionId,
String destination,
Message msg,
boolean transacted)
throws IOException,
JMSException
{
if(this.queues.get(destination) != null) {
this.p2p.send(sessionId, destination, msg, transacted);
} else if(this.topics.get(destination) != null) {
this.pubSub.send(sessionId, destination, msg, transacted);
} else {
String s = "destination '" + destination + "' does not exist!";
throw new InvalidDestinationException(s);
}
}
void sendInternal(String sessionId, String destination, Message msg)
throws IOException, JMSException
{
this.server.send(sessionId, destination, msg);
}
void sendInternal(String sessionId, String[] destinations, Message msg)
throws IOException, JMSException
{
this.server.send(sessionId, destinations, msg);
}
PeekMessage peek(String sessionId, String destination)
throws IOException, JMSException
{
return this.server.peek(sessionId, destination);
}
void acknowledge(String sessionId, PeekMessage msg)
throws IOException
{
this.server.acknowledge(sessionId, msg);
}
public Message receive(String sessionId,
String destination,
String consumerId)
throws IOException,
JMSException
{
return this.receive(sessionId, destination, consumerId, true);
}
Message receive(String sessionId,
String destination,
String consumerId,
boolean transacted)
throws IOException,
JMSException
{
Message msg = null;
if(this.queues.get(destination) != null) {
msg = this.p2p.receive(sessionId,
destination,
consumerId,
transacted);
if (log.isDebugEnabled()) log.debug("p2p receive: " + msg);
} else if(this.topics.get(destination) != null) {
msg = this.pubSub.receive(sessionId,
destination,
consumerId,
transacted);
if (log.isDebugEnabled()) log.debug("pubSub receive: " + msg);
} else {
String s = "destination '" + destination + "' does not exist!";
throw new InvalidDestinationException(s);
}
return msg;
}
Message receiveInternal(String sessionId, String destination)
throws IOException, JMSException
{
return this.server.receive(sessionId, destination);
}
public void commit(String sessionId) {
this.server.commit(sessionId);
}
public void rollback(String sessionId) {
this.server.rollback(sessionId);
}
public void stop() {
this.durSubs.close();
this.server.stop();
}
/**
* Thread used as a shutdown hook.
* <p/>
* Shuts down the server gracefully.
*/
class Shutdown extends Thread {
Shutdown() {
super("mom4j-Shutdown-Thread");
}
public void run() {
if(!Console.this.server.isRunning()) {
return;
}
log.info("Shutdown in progress ...");
Console.this.stop();
log.info("Done.");
}
}
}