Search in sources :

Example 1 with PEPService

use of org.jivesoftware.openfire.pep.PEPService in project Openfire by igniterealtime.

the class LeafNode method deleteItems.

/**
 * Deletes the list of published items from the node. Event notifications may be sent to
 * subscribers for the deleted items, as well as all connected resources of the service owner,
 * if the service is a PEP service.<p>
 *
 * When an affiliate has many subscriptions to the node, the affiliate will get a notification
 * for each set of items that affected the same list of subscriptions.<p>
 *
 * @param toDelete list of items that were deleted from the node.
 */
public void deleteItems(List<PublishedItem> toDelete) {
    // Remove deleted items from the database
    for (PublishedItem item : toDelete) {
        XMPPServer.getInstance().getPubSubModule().getPersistenceProvider().removePublishedItem(item);
        if (lastPublished != null && lastPublished.getID().equals(item.getID())) {
            lastPublished = null;
        }
    }
    if (isNotifiedOfRetract()) {
        // Broadcast notification deletion to subscribers
        // Build packet to broadcast to subscribers
        Message message = new Message();
        Element event = message.addChildElement("event", "http://jabber.org/protocol/pubsub#event");
        // Send notification that items have been deleted to subscribers and parent node
        // subscribers
        Set<NodeAffiliate> affiliatesToNotify = getAffiliatesToNotify();
        // TODO Use another thread for this (if # of subscribers is > X)????
        for (NodeAffiliate affiliate : affiliatesToNotify) {
            affiliate.sendDeletionNotifications(message, event, this, toDelete);
        }
        // XEP-0136 specifies that all connected resources of the owner of the PEP service should also get a notification.
        if (getService() instanceof PEPService) {
            final PEPService service = (PEPService) getService();
            Element items = event.addElement("items");
            items.addAttribute("node", getUniqueIdentifier().getNodeId());
            for (PublishedItem publishedItem : toDelete) {
                // Add retract information to the event notification
                Element item = items.addElement("retract");
                if (isItemRequired()) {
                    item.addAttribute("id", publishedItem.getID());
                }
                // Send the notification
                final Collection<ClientSession> sessions = SessionManager.getInstance().getSessions(service.getAddress().getNode());
                for (final ClientSession session : sessions) {
                    service.sendNotification(this, message, session.getAddress());
                }
                // Remove the added items information
                event.remove(items);
            }
        }
    }
}
Also used : Message(org.xmpp.packet.Message) PEPService(org.jivesoftware.openfire.pep.PEPService) Element(org.dom4j.Element) ClientSession(org.jivesoftware.openfire.session.ClientSession)

Example 2 with PEPService

use of org.jivesoftware.openfire.pep.PEPService in project Openfire by igniterealtime.

the class InMemoryPubSubPersistenceProvider method loadPEPServiceFromDB.

@Override
public PEPService loadPEPServiceFromDB(JID jid) {
    final PubSubService.UniqueIdentifier id = new PubSubService.UniqueIdentifier(jid.toString());
    final Lock lock = serviceIdToNodesCache.getLock(id);
    lock.lock();
    try {
        if (serviceIdToNodesCache.containsKey(id)) {
            final PEPService pepService = new PEPService(XMPPServer.getInstance(), jid);
            pepService.initialize();
            // The JDBC variant stores subscriptions in the database. The in-memory variant cannot rely on this.
            // Subscriptions have to be repopulated from the roster instead.
            XMPPServer.getInstance().getIQPEPHandler().addSubscriptionForRosterItems(pepService);
            return pepService;
        } else {
            return null;
        }
    } finally {
        lock.unlock();
    }
}
Also used : PEPService(org.jivesoftware.openfire.pep.PEPService) Lock(java.util.concurrent.locks.Lock)

Example 3 with PEPService

use of org.jivesoftware.openfire.pep.PEPService in project Openfire by igniterealtime.

the class CollectionNode method broadcastCollectionNodeEvent.

private void broadcastCollectionNodeEvent(Node child, Message notification) {
    // Get affected subscriptions (of this node and all parent nodes)
    Collection<NodeSubscription> subscriptions = new ArrayList<>();
    subscriptions.addAll(getSubscriptions(child));
    for (CollectionNode parentNode : getParents()) {
        subscriptions.addAll(parentNode.getSubscriptions(child));
    }
    // TODO Possibly use a thread pool for sending packets (based on the jids size)
    for (NodeSubscription subscription : subscriptions) {
        getService().sendNotification(subscription.getNode(), notification, subscription.getJID());
    }
    // XEP-0136 specifies that all connected resources of the owner of the PEP service should also get a notification
    if (getService() instanceof PEPService) {
        final Collection<ClientSession> sessions = SessionManager.getInstance().getSessions(getService().getAddress().getNode());
        for (final ClientSession session : sessions) {
            getService().sendNotification(child, notification, session.getAddress());
            for (CollectionNode parentNode : getParents()) {
                getService().sendNotification(parentNode, notification, session.getAddress());
            }
        }
    }
}
Also used : PEPService(org.jivesoftware.openfire.pep.PEPService) ClientSession(org.jivesoftware.openfire.session.ClientSession) ArrayList(java.util.ArrayList)

Example 4 with PEPService

use of org.jivesoftware.openfire.pep.PEPService in project Openfire by igniterealtime.

the class PrivateStorage method add.

/**
 * Stores private data. If the name and namespace of the element matches another
 * stored private data XML document, then replace it with the new one.
 *
 * @param data the data to store (XML element)
 * @param username the username of the account where private data is being stored
 */
public void add(String username, Element data) {
    if (!enabled) {
        return;
    }
    final JID owner = XMPPServer.getInstance().createJID(username, null);
    final PEPServiceManager serviceMgr = XMPPServer.getInstance().getIQPEPHandler().getServiceManager();
    PEPService pepService = serviceMgr.getPEPService(owner);
    if (pepService == null) {
        pepService = serviceMgr.create(owner);
    }
    Node node = pepService.getNode(data.getNamespaceURI());
    if (node == null) {
        PubSubEngine.CreateNodeResponse response = PubSubEngine.createNodeHelper(pepService, owner, pepService.getDefaultNodeConfiguration(true).getConfigurationForm().getElement(), data.getNamespaceURI(), PRIVATE_DATA_PUBLISHING_OPTIONS);
        node = response.newNode;
        if (node == null) {
            Log.error("Unable to create new PEP node, to be used to store private data. Error condition: {}", response.creationStatus.toXMPP());
            return;
        }
    }
    if (!(node instanceof LeafNode)) {
        Log.error("Unable to store private data into a PEP node. The node that is available is not a leaf node.");
        return;
    }
    data.detach();
    final Element item = DocumentHelper.createElement("item");
    item.addAttribute("id", "current");
    item.add(data);
    ((LeafNode) node).publishItems(owner, Collections.singletonList(item));
}
Also used : JID(org.xmpp.packet.JID) PEPServiceManager(org.jivesoftware.openfire.pep.PEPServiceManager) PEPService(org.jivesoftware.openfire.pep.PEPService) Node(org.jivesoftware.openfire.pubsub.Node) LeafNode(org.jivesoftware.openfire.pubsub.LeafNode) LeafNode(org.jivesoftware.openfire.pubsub.LeafNode) Element(org.dom4j.Element) PubSubEngine(org.jivesoftware.openfire.pubsub.PubSubEngine)

Example 5 with PEPService

use of org.jivesoftware.openfire.pep.PEPService in project Openfire by igniterealtime.

the class PubSubEngine method publishItemsToNode.

private void publishItemsToNode(PubSubService service, IQ iq, Element publishElement) {
    String nodeID = publishElement.attributeValue("node");
    Node node;
    JID from = iq.getFrom();
    // TODO Assuming that owner is the bare JID (as defined in the JEP). This can be replaced with an explicit owner specified in the packet
    JID owner = from.asBareJID();
    if (nodeID == null) {
        // XEP-0060 Section 7.2.3.3 - No node was specified. Return bad_request error
        // This suggests that Instant nodes should not be auto-created
        Element pubsubError = DocumentHelper.createElement(QName.get("nodeid-required", "http://jabber.org/protocol/pubsub#errors"));
        sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
        return;
    }
    // Optional Publish Options.
    final DataForm publishOptions = getPublishOptions(iq);
    // Look for the specified node
    node = service.getNode(nodeID);
    if (node == null) {
        if (service instanceof PEPService && service.isServiceAdmin(owner) && canAutoCreate(publishOptions)) {
            // If it is a PEP service & publisher is service owner - auto create nodes.
            CreateNodeResponse response = createNodeHelper(service, iq.getFrom(), iq.getChildElement().element("configure"), publishElement.attributeValue("node"), publishOptions);
            if (response.newNode == null) {
                // New node creation failed. Since pep#auto-create is advertised
                // in disco#info, node creation error should be sent to the client.
                sendErrorPacket(iq, response.creationStatus, response.pubsubError);
                return;
            } else {
                // Node creation succeeded, set node to newNode.
                node = response.newNode;
            }
        } else {
            // Node does not exist. Return item-not-found error
            sendErrorPacket(iq, PacketError.Condition.item_not_found, null);
            return;
        }
    } else {
        // Check if the preconditions defined in the publish options (if any) are met.
        if (!nodeMeetsPreconditions(node, publishOptions)) {
            Element pubsubError = DocumentHelper.createElement(QName.get("precondition-not-met", "http://jabber.org/protocol/pubsub#errors"));
            sendErrorPacket(iq, PacketError.Condition.conflict, pubsubError);
            return;
        }
    }
    if (!node.getPublisherModel().canPublish(node, owner) && !service.isServiceAdmin(owner)) {
        // Entity does not have sufficient privileges to publish to node
        sendErrorPacket(iq, PacketError.Condition.forbidden, null);
        return;
    }
    if (node.isCollectionNode()) {
        // Node is a collection node. Return feature-not-implemented error
        Element pubsubError = DocumentHelper.createElement(QName.get("unsupported", "http://jabber.org/protocol/pubsub#errors"));
        pubsubError.addAttribute("feature", "publish");
        sendErrorPacket(iq, PacketError.Condition.feature_not_implemented, pubsubError);
        return;
    }
    LeafNode leafNode = (LeafNode) node;
    Iterator<Element> itemElements = publishElement.elementIterator("item");
    // Check that an item was included if node persist items or includes payload
    if (!itemElements.hasNext() && leafNode.isItemRequired()) {
        Element pubsubError = DocumentHelper.createElement(QName.get("item-required", "http://jabber.org/protocol/pubsub#errors"));
        sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
        return;
    }
    // includes payload
    if (itemElements.hasNext() && !leafNode.isItemRequired()) {
        Element pubsubError = DocumentHelper.createElement(QName.get("item-forbidden", "http://jabber.org/protocol/pubsub#errors"));
        sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
        return;
    }
    List<Element> items = new ArrayList<>();
    List<Element> entries;
    Element payload;
    while (itemElements.hasNext()) {
        Element item = itemElements.next();
        entries = item.elements();
        payload = entries.isEmpty() ? null : entries.get(0);
        // in notifications
        if (payload == null && leafNode.isPayloadDelivered()) {
            Element pubsubError = DocumentHelper.createElement(QName.get("payload-required", "http://jabber.org/protocol/pubsub#errors"));
            sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
            return;
        }
        // Check that the payload (if any) contains only one child element
        if (entries.size() > 1) {
            Element pubsubError = DocumentHelper.createElement(QName.get("invalid-payload", "http://jabber.org/protocol/pubsub#errors"));
            sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
            return;
        }
        items.add(item);
    }
    // Return success operation
    router.route(IQ.createResultIQ(iq));
    // Publish item and send event notifications to subscribers
    leafNode.publishItems(from, items);
}
Also used : PEPService(org.jivesoftware.openfire.pep.PEPService) Element(org.dom4j.Element) DataForm(org.xmpp.forms.DataForm)

Aggregations

PEPService (org.jivesoftware.openfire.pep.PEPService)8 Element (org.dom4j.Element)4 ClientSession (org.jivesoftware.openfire.session.ClientSession)3 ArrayList (java.util.ArrayList)2 PEPServiceManager (org.jivesoftware.openfire.pep.PEPServiceManager)2 LeafNode (org.jivesoftware.openfire.pubsub.LeafNode)2 Node (org.jivesoftware.openfire.pubsub.Node)2 Connection (java.sql.Connection)1 PreparedStatement (java.sql.PreparedStatement)1 ResultSet (java.sql.ResultSet)1 SQLException (java.sql.SQLException)1 List (java.util.List)1 Lock (java.util.concurrent.locks.Lock)1 PubSubEngine (org.jivesoftware.openfire.pubsub.PubSubEngine)1 PublishedItem (org.jivesoftware.openfire.pubsub.PublishedItem)1 DataForm (org.xmpp.forms.DataForm)1 JID (org.xmpp.packet.JID)1 Message (org.xmpp.packet.Message)1