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);
}
}
}
}
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();
}
}
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());
}
}
}
}
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));
}
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);
}
Aggregations