All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ow2.petals.ws.notification.WsnManager Maven / Gradle / Ivy

/**
 * PETALS - PETALS Services Platform.
 * Copyright (c) 2007 EBM Websourcing, http://www.ebmwebsourcing.com/
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 * -------------------------------------------------------------------------
 * $Id$
 * -------------------------------------------------------------------------
 */

package org.ow2.petals.ws.notification;

import java.net.URI;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.xml.namespace.QName;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.soap.SOAPEnvelope;
import org.ow2.petals.ws.addressing.EndpointReference;
import org.ow2.petals.ws.client.SoapClient;
import org.ow2.petals.ws.fault.WsnFault;
import org.ow2.petals.ws.notification.handlers.request.WSNHandler;
import org.ow2.petals.ws.topic.Topic;
import org.ow2.petals.ws.topic.TopicNamespace;
import org.ow2.petals.ws.topic.TopicSet;
import org.ow2.petals.ws.topic.WstConstants;
import org.ow2.petals.ws.topic.WstHelper;

/**
 * The WebService notification manager
 * 
 * @author chamerling - eBM WebSourcing
 * 
 */
public class WsnManager {

    /**
     * It's me !
     */
    protected EndpointReference producerEPR;

    /**
     * All the topics names
     */
    protected Set allTopicNames;

    
    protected String subscriptionPath = null;

    /**
     * Map of EPR to current subscriptions
     */
    protected Map subscriptionsByEPR;;

    /**
     * Hierarchical topic
     */
    protected TopicSet topicSet;

    /**
     * The persistence manager to be used. Can be null, in this case nothing
     * will be persisted.
     */
    private WsnPersistance persistance;

    /**
     * Map of handlers which are used to handle requests
     */
    protected Map wsnHandlers;

    /**
     * FIXME : Use apache commons with a wrapper
     */
    private Logger logger;

    /**
     * Creates a new instance of {@link WsnManager}
     * 
     * @param logger
     * 
     */
    public WsnManager(Logger logger) {
        super();
        this.allTopicNames = new HashSet();
        this.subscriptionsByEPR = new Hashtable();
        this.topicSet = new TopicSet();
        this.wsnHandlers = new HashMap();
        this.logger = logger;
    }

    /**
     * Add a handler
     * 
     * @param wsnHandler
     */
    public void addHandler(WSNHandler wsnHandler) {
        logger.fine("Adding handler for action " + wsnHandler.getActionURI());
        wsnHandler.setManager(this);
        this.wsnHandlers.put(wsnHandler.getActionURI(), wsnHandler);
    }

    /**
     * Get handler for specified action.
     * 
     * @param actionURI
     * @return the {@link WSNHandler} or nulll if not found
     */
    public WSNHandler getHandler(String actionURI) {
        logger.fine("Get handler for action " + actionURI);
        return this.wsnHandlers.get(actionURI);
    }

    /**
     * Reload the subscriptions for the given topic, the subscriptions are
     * persisted in files.
     * 
     * @param topicName
     * @throws WsnFault
     */
    public void reloadSubscriptions(QName topicName) throws WsnFault {
        logger.fine("Reloading subscriptions for topic " + topicName);

        if (persistance == null) {
            throw new WsnFault(
                    "The subscriptions can not be reloaded since persistance manager is null");
        }

        WSNHandler subHandler = wsnHandlers.get(WsnConstants.SUBSCRIBE_URI);
        if (subHandler == null) {
            throw new WsnFault("The subscription handler can not be found");
        }

        // retrieve persisted envelopes (initial messages from WSN consumers)
        List envelopes = this.persistance.getSubscriptionEnvelopesForTopic(topicName);

        // remove old persistence files
        if (envelopes.size() > 0) {
            this.persistance.cleanSubscriptions(topicName);
        }

        for (SOAPEnvelope envelope : envelopes) {
            if (logger.isLoggable(Level.FINE)) {
                logger.fine("Reload subscription for initial envelope : " + envelope.toString());
            }

            // call handler
            SOAPEnvelope response = subHandler.handle(envelope);

            if (logger.isLoggable(Level.FINE)) {
                logger.fine("Subscription reloaded, response of the handler is : "
                        + response.toString());
            }
        }
    }

    /**
     * Add a subscription
     * 
     * @param subscription
     */
    public synchronized void addSubscription(Subscription subscription) throws WsnFault {
        logger.fine("Adding subscription for consumer " + subscription.getConsumerEPR()
                + " on topic " + subscription.getFilter().getTopicName());
        EndpointReference epr = subscription.getConsumerEPR();
        this.subscriptionsByEPR.put(epr, subscription);

        if (this.persistance != null) {
            try {
                this.persistance.persist(subscription);
            } catch (Exception e) {
                throw new WsnFault("Can not persist subscription");
            }
        }
    }

    /**
     * Add a new topic.
     * 
     * @param topicName
     * @return
     * @throws WsnFault
     */
    public Topic addTopic(QName topicName) throws WsnFault {
        logger.fine("Creating new topic " + topicName);
        String namespace = topicName.getNamespaceURI();
        TopicNamespace topicSpace = getTopicNamespace(namespace);

        // no topic namespace has been found, create it
        if (topicSpace == null) {
            topicSpace = addTopicNamespace(namespace);
        }

        String localName = topicName.getLocalPart();
        Topic topic = new Topic(localName, topicSpace);

        // save to topic space
        topicSpace.addTopic(topic);

        // save topic name in set
        allTopicNames.add(topicName);

        // persist
        if (persistance != null) {
            persistance.persist(topic);
        }

        return topic;
    }

    /**
     * 
     * @param topicName
     * @return
     * @throws WsnFault
     */
    public boolean deleteTopic(QName topicName) throws WsnFault {
        logger.fine("Deleting topic " + topicName);
        boolean result = true;
        Topic topic = null;
        String name = WstHelper.getRootTopicName(topicName);

        TopicNamespace topicSpace = getTopicNamespace(topicName.getNamespaceURI());
        if (topicSpace == null) {
            logger.fine("Topic has not been found");
            result = false;
        } else {
            // remove topic from the topic space
            topic = topicSpace.getTopic(name);
            if (topic != null) {
                result = topicSpace.removeTopic(name);
            }
        }

        // look if a topic is available in the set
        if (allTopicNames.contains(topicName)) {
            logger.fine("Topic has been found, delete it...");
            result = (result && allTopicNames.remove(topicName));
        }

        return result;
    }

    /**
     * Clean topic is removing the persistance directory...
     * 
     * @return
     */
    public boolean cleanTopic(QName topicName) {
        logger.fine("Cleaning Topic " + topicName);
        boolean result = false;
        if (topicName != null && persistance != null) {
            logger.fine("Delete the persistance directory for the topic " + topicName);
            result = persistance.delete(WstHelper.getRootTopicName(topicName));
        }

        return result;
    }

    /**
     * 
     * @param namespace
     * @return
     * @throws WsnFault
     */
    public TopicNamespace addTopicNamespace(String namespace) throws WsnFault {
        TopicNamespace tns = new TopicNamespace(namespace);
        tns.setName("ResourcePropertiesTopicSpace");
        topicSet.addTopicNamespace(tns);
        return tns;
    }

    /**
     * Get the current notification message for the given topic
     * 
     * @param topicPath
     * @return the current message of the topic
     */
    public NotificationMessage getCurrentMessage(QName topicPath) throws WsnFault {
        logger.fine("Getting current message on topic " + topicPath);
        Topic topic = getTopic(topicPath);

        if (topic == null) {
            throw new WsnFault("Topic not found");
        }

        NotificationMessage message = topic.getCurrentMessage();

        if (message == null) {
            throw new WsnFault("No message in topic");
        }
        return message;
    }

    /**
     * Get the topic
     * 
     * @param topicName
     * @return
     */
    public Topic getTopic(QName topicName) {
        TopicNamespace topicSpace = getTopicNamespace(topicName.getNamespaceURI());

        if (topicSpace == null)
            return null;

        return topicSpace.getTopic(topicName.getLocalPart());
    }

    /**
     * 
     * @return
     */
    public QName[] getTopicExpression() {
        QName[] array = new QName[allTopicNames.size()];
        return (QName[]) allTopicNames.toArray(array);
    }

    /**
     * 
     * @return
     */
    public String[] getTopicExpressionDialect() {
        return new String[] { WstConstants.CONCRETE_TOPIC_URI };
    }

    public TopicNamespace getTopicNamespace(String namespace) {
        return getTopicSet().getTopicNamespace(namespace);
    }

    public TopicSet getTopicSet() {
        return topicSet;
    }

    /**
     * There is already a subcriber for the given EPR ?
     * 
     * @param subscriptionEPR
     * @return
     */
    public boolean hasSubscription(EndpointReference subscriptionEPR) {
        return this.subscriptionsByEPR.containsKey(subscriptionEPR);
    }

    /**
     * There is already a topic with the given name ?
     * 
     * @param topicName
     * @return
     */
    public boolean hasTopic(QName topicName) {
        return allTopicNames.contains(topicName);
    }

    /**
     * Publish a message to a topic
     * 
     * @param topicName
     * @param content
     * @param soapClient
     * @throws WsnFault
     */
    public void publish(QName topicName, OMElement content, SoapClient soapClient) throws WsnFault {
        publish(topicName, new OMElement[] { content }, soapClient);
    }

    /**
     * Public a message to a topic
     * 
     * @param topicName
     * @param content
     * @param soapClient
     * @throws WsnFault
     */
    public void publish(QName topicName, OMElement[] content, SoapClient soapClient)
            throws WsnFault {
        logger.fine("Publishing new notification message on topic " + topicName);
        NotificationMessage message = new NotificationMessage();
        for (OMElement element : content) {
            message.addMessageContent(element);
        }
        message.setTopic(topicName);

        // give the message to each subscription so it can decide if it
        // should be sent or not
        Iterator i = getSubscriptions().iterator();
        while (i.hasNext()) {
            Subscription sub = i.next();
            logger.fine("Send notification to consumer " + sub.getConsumerEPR().getAddress());
            SOAPEnvelope env = sub.publish(message, soapClient);
            if (logger.isLoggable(Level.FINE)) {
                logger.fine("Notification result : " + env.toString());
            }
        }

        //
        // if a topic was used, record the message as the 'current' message
        // for the topic (will be returned by getCurrentMessage())
        //
        if (topicName != null) {
            Topic topic = getTopic(topicName);
            if (topic != null) {
                topic.setCurrentMessage(message);
            }
        }
    }

    /**
     * Get the subscriptions
     * 
     * @return
     */
    public synchronized Collection getSubscriptions() {
        return Collections.unmodifiableCollection(subscriptionsByEPR.values());
    }

    /**
     * Removing a subscription from its EPR will remove all the subscriptions
     * for this EPR since a notification consumer can subscribe several times.
     * 
     * @param epr
     */
    public synchronized void removeSubscription(EndpointReference epr) {
        URI address = epr.getAddress();
        logger.fine("Removing subscription(s) for " + epr.getAddress());

        Iterator iter = subscriptionsByEPR.keySet().iterator();
        while (iter.hasNext()) {
            EndpointReference tmp = iter.next();
            if (tmp.getAddress().equals(address)) {
                Subscription subscription = subscriptionsByEPR.get(tmp);
                iter.remove();
                if (persistance != null && subscription != null) {
                    try {
                        persistance.delete(subscription);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    }

    /**
     * @return the producerEPR
     */
    public EndpointReference getProducerEPR() {
        return this.producerEPR;
    }

    /**
     * @param producerEPR
     *            the producerEPR to set
     */
    public void setProducerEPR(EndpointReference producerEPR) {
        this.producerEPR = producerEPR;
    }

    /**
     * 
     * @return
     */
    public WsnPersistance getPersistance() {
        return persistance;
    }

    /**
     * 
     * @param persistance
     */
    public void setPersistance(WsnPersistance persistance) {
        this.persistance = persistance;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy