package org.servicemix.ws.notification.impl;
import org.activemq.ActiveMQConnection;
import org.activemq.ActiveMQConnectionFactory;
import org.activemq.message.ActiveMQTopic;
import org.servicemix.ws.notification.NotificationBroker;
import org.servicemix.ws.notification.NotificationConsumer;
import org.servicemix.ws.notification.NotificationException;
import org.servicemix.ws.notification.PublisherRegistrationManager;
import org.servicemix.ws.notification.SubscriptionManager;
import org.servicemix.ws.notification.impl.invoke.NotificationConsumerInvoker;
import org.servicemix.ws.notification.impl.invoke.InvokerSupport;
import org.servicemix.ws.xmlbeans.addressing.v2003_03.EndpointReferenceType;
import org.servicemix.ws.xmlbeans.notification.base.GetCurrentMessageDocument;
import org.servicemix.ws.xmlbeans.notification.base.GetCurrentMessageResponseDocument;
import org.servicemix.ws.xmlbeans.notification.base.NotificationMessageHolderType;
import org.servicemix.ws.xmlbeans.notification.base.NotifyDocument;
import org.servicemix.ws.xmlbeans.notification.base.NotifyDocument.Notify;
import org.servicemix.ws.xmlbeans.notification.base.SubscribeDocument;
import org.servicemix.ws.xmlbeans.notification.base.SubscribeDocument.Subscribe;
import org.servicemix.ws.xmlbeans.notification.base.SubscribeResponseDocument;
import org.servicemix.ws.xmlbeans.notification.brokered.NotificationBrokerRPDocument;
import org.servicemix.ws.xmlbeans.notification.brokered.NotificationBrokerRPDocument.NotificationBrokerRP;
import org.servicemix.ws.xmlbeans.notification.brokered.RegisterPublisherDocument;
import org.servicemix.ws.xmlbeans.notification.brokered.RegisterPublisherDocument.RegisterPublisher;
import org.servicemix.ws.xmlbeans.notification.brokered.RegisterPublisherResponseDocument;
import org.servicemix.ws.xmlbeans.notification.brokered.RegisterPublisherResponseDocument.RegisterPublisherResponse;
import org.servicemix.ws.xmlbeans.resource.properties.GetResourcePropertyDocument;
import org.servicemix.ws.xmlbeans.resource.properties.GetResourcePropertyResponseDocument;
import javax.jms.JMSException;
import javax.jms.Topic;
import java.io.IOException;
import java.util.Calendar;
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 NotificationException("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 NotificationException(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();
ActiveMQPublisherRegistration publisher = getPublisher(producerReference);
publisher.notify(topic, messageHolder.getMessage());
}
}
catch (IOException e) {
throw new NotificationException(e);
}
catch (JMSException e) {
throw new NotificationException(e);
}
}
protected ActiveMQPublisherRegistration getPublisher(EndpointReferenceType producerReference) {
ActiveMQPublisherRegistration publisher = null;
if (producerReference != null) {
publisher = publisherManager.getProducer(producerReference);
}
if (publisher == null) {
publisher = anonymousPublisher;
}
return publisher;
}
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 NotificationException("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.setDispatcher(createDispatcher(subscribe));
subscription.start();
}
catch (JMSException e) {
throw new NotificationException(e);
}
EndpointReferenceType endpointReference = subscriptionManager.register(subscription);
subscription.setEndpointReference(endpointReference);
// Send response.
SubscribeResponseDocument responseDoc = SubscribeResponseDocument.Factory.newInstance();
responseDoc.addNewSubscribeResponse().setSubscriptionReference(endpointReference);
return responseDoc;
}
protected InvokerSupport createDispatcher(SubscribeDocument.Subscribe subscribe) throws NotificationException {
return new NotificationConsumerInvoker(createNotificationConsumer(subscribe.getConsumerReference()));
}
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 NotificationException("Not supported");
}
public GetResourcePropertyResponseDocument getResourceProperty(EndpointReferenceType resource, GetResourcePropertyDocument request) {
return xmlResourceProperties.getResourceProperty(null, request);
}
public PublisherRegistrationManager getPublisherManager() {
return publisherManager;
}
public SubscriptionManager getSubscriptionManager() {
return subscriptionManager;
}
}