package org.activemq.ws.notification.impl;
import java.io.IOException;
import java.util.Calendar;
import javax.jms.JMSException;
import javax.jms.Topic;
import org.activemq.ActiveMQConnection;
import org.activemq.ActiveMQConnectionFactory;
import org.activemq.message.ActiveMQTopic;
import org.activemq.ws.notification.NotificationBroker;
import org.activemq.ws.notification.NotificationConsumer;
import org.activemq.ws.notification.PublisherRegistrationManager;
import org.activemq.ws.notification.SubscriptionManager;
import org.activemq.ws.xmlbeans.addressing.v2003_03.EndpointReferenceType;
import org.activemq.ws.xmlbeans.notification.base.GetCurrentMessageDocument;
import org.activemq.ws.xmlbeans.notification.base.GetCurrentMessageResponseDocument;
import org.activemq.ws.xmlbeans.notification.base.NotificationMessageHolderType;
import org.activemq.ws.xmlbeans.notification.base.NotifyDocument;
import org.activemq.ws.xmlbeans.notification.base.SubscribeDocument;
import org.activemq.ws.xmlbeans.notification.base.SubscribeResponseDocument;
import org.activemq.ws.xmlbeans.notification.base.NotifyDocument.Notify;
import org.activemq.ws.xmlbeans.notification.base.SubscribeDocument.Subscribe;
import org.activemq.ws.xmlbeans.notification.brokered.NotificationBrokerRPDocument;
import org.activemq.ws.xmlbeans.notification.brokered.RegisterPublisherDocument;
import org.activemq.ws.xmlbeans.notification.brokered.RegisterPublisherResponseDocument;
import org.activemq.ws.xmlbeans.notification.brokered.NotificationBrokerRPDocument.NotificationBrokerRP;
import org.activemq.ws.xmlbeans.notification.brokered.RegisterPublisherDocument.RegisterPublisher;
import org.activemq.ws.xmlbeans.notification.brokered.RegisterPublisherResponseDocument.RegisterPublisherResponse;
import org.activemq.ws.xmlbeans.resource.properties.GetResourcePropertyDocument;
import org.activemq.ws.xmlbeans.resource.properties.GetResourcePropertyResponseDocument;
public class ActiveMQNotificationBroker implements NotificationBroker {
private ActiveMQPublisherRegistrationManager publisherManager = new ActiveMQPublisherRegistrationManager();
private ActiveMQSubscriptionManager subscriptionManager = new ActiveMQSubscriptionManager();
private ActiveMQConnectionFactory factory;
private ActiveMQConnection connection;
private ActiveMQPublisherRegistration anonymousPublisher;
private NotificationBrokerRP resourceProperties;
private XmlObjectResourceProperties xmlResourceProperties;
public ActiveMQNotificationBroker() throws JMSException {
this("vm://localhost");
}
public ActiveMQNotificationBroker(String url) throws JMSException {
this(new ActiveMQConnectionFactory(url));
}
public ActiveMQNotificationBroker(ActiveMQConnectionFactory factory) throws JMSException {
this.factory = factory;
connection = (ActiveMQConnection) factory.createConnection();
connection.start();
anonymousPublisher = new ActiveMQPublisherRegistration(connection);
NotificationBrokerRPDocument document = NotificationBrokerRPDocument.Factory.newInstance();
resourceProperties = document.addNewNotificationBrokerRP();
resourceProperties.setFixedTopicSet(false);
resourceProperties.setRequiresRegistration(false);
resourceProperties.setTopicExpressionDialectsArray(new String[]{"ActiveMQ"});
xmlResourceProperties = new XmlObjectResourceProperties(resourceProperties);
}
public ActiveMQConnection getConnection() {
return connection;
}
public RegisterPublisherResponseDocument registerPublisher(RegisterPublisherDocument requestDoc) {
// Check request.
RegisterPublisher publisherInfo = requestDoc.getRegisterPublisher();
ActiveMQTopic topic = TopicExpressionConverter.toActiveMQTopic(publisherInfo.getTopicArray());
Calendar terminationTime = publisherInfo.getInitialTerminationTime();
if( terminationTime!=null ) {
// Termination time cannot be in the past
if( terminationTime.before( Calendar.getInstance() ) ) {
// Is this the right way to fault??
throw new RuntimeException("Termination time cannot be in the past.");
}
// We could fault here if the time is too far in the future.
} else {
// We could default a sensible timeout here.
}
// Create publisher and assoicate an EndpointReference with it.
EndpointReferenceType registrationEndpointReference;
try {
ActiveMQPublisherRegistration publisher = new ActiveMQPublisherRegistration(connection);
registrationEndpointReference = publisherManager.register(publisher);
publisher.setEndpointReference(registrationEndpointReference);
publisher.setTerminationTime(terminationTime);
publisher.setDemand(publisherInfo.getDemand());
if( publisherInfo.getDemand() ) {
publisher.setPublisherReference(publisherInfo.getPublisherReference());
}
publisher.setTopic( topic );
publisher.start();
} catch (JMSException e) {
throw new RuntimeException(e);
}
// Send response.
RegisterPublisherResponseDocument responseDoc = RegisterPublisherResponseDocument.Factory.newInstance();
RegisterPublisherResponse response = responseDoc.addNewRegisterPublisherResponse();
response.setPublisherRegistrationReference( registrationEndpointReference );
return responseDoc;
}
public void notify(NotifyDocument requestDoc) {
try {
Notify notify = requestDoc.getNotify();
NotificationMessageHolderType[] messageHolders = notify.getNotificationMessageArray();
for (int i = 0; i < messageHolders.length; i++) {
NotificationMessageHolderType messageHolder = messageHolders[i];
Topic topic = TopicExpressionConverter.toActiveMQTopic(messageHolder.getTopic());
EndpointReferenceType producerReference = messageHolder.getProducerReference();
if( producerReference != null ) {
ActiveMQPublisherRegistration publisher = publisherManager.getProducer(producerReference);
publisher.notify( topic, messageHolder.getMessage() );
} else {
anonymousPublisher.notify( topic, messageHolder.getMessage() );
}
}
} catch (IOException e) {
throw new RuntimeException(e);
} catch (JMSException e) {
throw new RuntimeException(e);
}
}
public SubscribeResponseDocument Subscribe(SubscribeDocument requestDoc) {
Subscribe subscribe = requestDoc.getSubscribe();
Calendar terminationTime = subscribe.getInitialTerminationTime();
if( terminationTime!=null ) {
// Termination time cannot be in the past
if( terminationTime.before( Calendar.getInstance() ) ) {
// Is this the right way to fault??
throw new RuntimeException("Termination time cannot be in the past.");
}
// We could fault here if the time is too far in the future.
} else {
// We could default a sensible timeout here.
}
ActiveMQSubscription subscription;
try {
subscription = new ActiveMQSubscription(connection);
subscription.setTopicExpression(subscribe.getTopicExpression());
subscription.setConsumerReference(subscribe.getConsumerReference());
subscription.setPrecondition(subscribe.getPrecondition());
subscription.setSelector(subscribe.getSelector());
subscription.setSubscriptionPolicy(subscribe.getSubscriptionPolicy());
subscription.setTopicExpression(subscribe.getTopicExpression());
subscription.setUseNotify(subscribe.getUseNotify());
subscription.setConsumer( createNotificationConsumer(subscribe.getConsumerReference()) );
subscription.start();
} catch (JMSException e) {
throw new RuntimeException(e);
}
EndpointReferenceType endpointReference = subscriptionManager.register( subscription );
subscription.setEndpointReference(endpointReference);
// Send response.
SubscribeResponseDocument responseDoc = SubscribeResponseDocument.Factory.newInstance();
responseDoc.addNewSubscribeResponse().setSubscriptionReference(endpointReference);
return responseDoc;
}
protected NotificationConsumer createNotificationConsumer(final EndpointReferenceType consumerReference) {
return new NotificationConsumer() {
public void notify(NotifyDocument notify) {
System.out.println("WS invoke not yet implemented");
System.out.println("Target: "+consumerReference);
System.out.println("Notify Message: "+notify);
}
};
}
public GetCurrentMessageResponseDocument getCurrentMessage(GetCurrentMessageDocument request) {
throw new RuntimeException("Not supported");
}
public GetResourcePropertyResponseDocument getResourceProperty(EndpointReferenceType resource, GetResourcePropertyDocument request) {
return xmlResourceProperties.getResourceProperty(null, request);
}
public PublisherRegistrationManager getPublisherManager() {
return publisherManager;
}
public SubscriptionManager getSubscriptionManager() {
return subscriptionManager;
}
}