Commit 32867543 authored by Matt Tucker's avatar Matt Tucker Committed by matt

Additional pubsub work.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3604 b35dd754-fafc-0310-a699-88a17e54d16e
parent 31acfb6b
...@@ -128,6 +128,7 @@ public class CollectionNode extends Node { ...@@ -128,6 +128,7 @@ public class CollectionNode extends Node {
} }
void removeChildNode(Node child) { void removeChildNode(Node child) {
// TODO Send notification to subscribers?
nodes.remove(child.getNodeID()); nodes.remove(child.getNodeID());
} }
......
...@@ -70,7 +70,7 @@ public class DefaultNodeConfiguration { ...@@ -70,7 +70,7 @@ public class DefaultNodeConfiguration {
/** /**
* Flag that indicates whether to send items to new subscribers. * Flag that indicates whether to send items to new subscribers.
*/ */
private boolean sendItemSubscribe; private boolean sendItemSubscribe = false;
/** /**
* Publisher model that specifies who is allowed to publish items to the node. * Publisher model that specifies who is allowed to publish items to the node.
*/ */
......
...@@ -13,6 +13,7 @@ package org.jivesoftware.wildfire.pubsub; ...@@ -13,6 +13,7 @@ package org.jivesoftware.wildfire.pubsub;
import org.xmpp.packet.JID; import org.xmpp.packet.JID;
import org.xmpp.packet.Message; import org.xmpp.packet.Message;
import org.dom4j.Element;
import java.util.*; import java.util.*;
...@@ -60,29 +61,126 @@ public class NodeAffiliate { ...@@ -60,29 +61,126 @@ public class NodeAffiliate {
return node.getSubscriptions(jid); return node.getSubscriptions(jid);
} }
/**
* Sends an event notification for the published items to the affiliate. The event
* notification may contain zero, one or many published items based on the items
* included in the original publication. If the affiliate has many subscriptions and
* many items were published then the affiliate will get a notification for each set
* of items that affected the same subscriptions.
*
* @param notification the message to sent to the subscribers. The message will be completed
* with the items to include in each notification.
* @param event the event Element included in the notification message. Passed as an
* optimization to avoid future look ups.
* @param node the leaf node where the items where published.
* @param publishedItems the list of items that were published. Could be an empty list.
*/
void sendPublishedNotifications(Message notification, Element event, LeafNode node,
List<PublishedItem> publishedItems) {
if (!publishedItems.isEmpty()) {
Map<List<NodeSubscription>, List<PublishedItem>> itemsBySubs =
getItemsBySubscriptions(node, publishedItems);
// Send one notification for published items that affect the same subscriptions
for (List<NodeSubscription> nodeSubscriptions : itemsBySubs.keySet()) {
// Add items information
Element items = event.addElement("items");
items.addAttribute("node", node.getNodeID());
for (PublishedItem publishedItem : itemsBySubs.get(nodeSubscriptions)) {
// Add item information to the event notification
Element item = items.addElement("item");
if (node.isItemRequired()) {
item.addAttribute("id", publishedItem.getID());
}
if (node.isPayloadDelivered()) {
item.add(publishedItem.getPayload().createCopy());
}
}
// Send the event notification
sendEventNotification(notification, node, nodeSubscriptions);
// Remove the added items information
event.remove(items);
}
}
else {
// Filter affiliate subscriptions and only use approved and configured ones
List<NodeSubscription> affectedSubscriptions = new ArrayList<NodeSubscription>();;
for (NodeSubscription subscription : getSubscriptions()) {
if (subscription.canSendEventNotification(node, null)) {
affectedSubscriptions.add(subscription);
}
}
// Add item information to the event notification
Element items = event.addElement("items");
items.addAttribute("node", node.getNodeID());
// Send the event notification
sendEventNotification(notification, node, affectedSubscriptions);
// Remove the added items information
event.remove(items);
}
}
/**
* Sends an event notification to the affiliate for the deleted items. The event
* notification may contain one or many published items based on the items included
* in the original publication. If the affiliate has many subscriptions and many
* items were deleted then the affiliate will get a notification for each set
* of items that affected the same subscriptions.
*
* @param notification the message to sent to the subscribers. The message will be completed
* with the items to include in each notification.
* @param event the event Element included in the notification message. Passed as an
* optimization to avoid future look ups.
* @param node the leaf node where the items where deleted from.
* @param publishedItems the list of items that were deleted.
*/
void sendDeletionNotifications(Message notification, Element event, LeafNode node,
List<PublishedItem> publishedItems) {
if (!publishedItems.isEmpty()) {
Map<List<NodeSubscription>, List<PublishedItem>> itemsBySubs =
getItemsBySubscriptions(node, publishedItems);
// Send one notification for published items that affect the same subscriptions
for (List<NodeSubscription> nodeSubscriptions : itemsBySubs.keySet()) {
// Add items information
Element items = event.addElement("items");
items.addAttribute("node", node.getNodeID());
for (PublishedItem publishedItem : itemsBySubs.get(nodeSubscriptions)) {
// Add retract information to the event notification
Element item = items.addElement("retract");
if (node.isItemRequired()) {
item.addAttribute("id", publishedItem.getID());
}
}
// Send the event notification
sendEventNotification(notification, node, nodeSubscriptions);
// Remove the added items information
event.remove(items);
}
}
}
/** /**
* Sends an event notification to each affected subscription of the affiliate. If the owner * Sends an event notification to each affected subscription of the affiliate. If the owner
* has many subscriptions from the same full JID then a single notification is going to be * has many subscriptions from the same full JID then a single notification is going to be
* sent including a detail of the subscription IDs for which the notification is being sent.<p> * sent including a detail of the subscription IDs for which the notification is being sent.<p>
* *
* Event notifications may include notifications of new published items or of items that
* were deleted.<p>
*
* The original publication to the node may or may not contain a {@link PublishedItem}. The * The original publication to the node may or may not contain a {@link PublishedItem}. The
* subscriptions of the affiliation will be filtered based on the published item (if one was * subscriptions of the affiliation will be filtered based on the published item (if one was
* specified), the subscription status and originating node. * specified), the subscription status and originating node.
* *
* @param notification the message to send containing the event notification. * @param notification the message to send containing the event notification.
* @param node the node that received a new publication. * @param node the node that received a new publication.
* @param publishedItem the item was was published in the publication or null if none * @param notifySubscriptions list of subscriptions that were affected and are going to be
* was published. * included in the notification message. The list should not be empty.
*/ */
public void sendEventNotification(Message notification, LeafNode node, private void sendEventNotification(Message notification, LeafNode node,
PublishedItem publishedItem) { List<NodeSubscription> notifySubscriptions) {
// Filter affiliate subscriptions and only use approved and configured ones
List<NodeSubscription> notifySubscriptions = new ArrayList<NodeSubscription>();
for (NodeSubscription subscription : getSubscriptions()) {
if (subscription.canSendEventNotification(node, publishedItem)) {
notifySubscriptions.add(subscription);
}
}
if (node.isMultipleSubscriptionsEnabled()) { if (node.isMultipleSubscriptionsEnabled()) {
// Group subscriptions with the same subscriber JID // Group subscriptions with the same subscriber JID
Map<JID, Collection<String>> groupedSubs = new HashMap<JID, Collection<String>>(); Map<JID, Collection<String>> groupedSubs = new HashMap<JID, Collection<String>>();
...@@ -112,6 +210,43 @@ public class NodeAffiliate { ...@@ -112,6 +210,43 @@ public class NodeAffiliate {
} }
} }
private Map<List<NodeSubscription>, List<PublishedItem>> getItemsBySubscriptions(LeafNode node,
List<PublishedItem> publishedItems) {
// Identify which subscriptions can receive each item
Map<PublishedItem, List<NodeSubscription>> subsByItem =
new HashMap<PublishedItem, List<NodeSubscription>>();
// Filter affiliate subscriptions and only use approved and configured ones
Collection<NodeSubscription> subscriptions = getSubscriptions();
for (PublishedItem publishedItem : publishedItems) {
for (NodeSubscription subscription : subscriptions) {
if (subscription.canSendEventNotification(node, publishedItem)) {
List<NodeSubscription> nodeSubscriptions = subsByItem.get(publishedItem);
if (nodeSubscriptions == null) {
nodeSubscriptions = new ArrayList<NodeSubscription>();
subsByItem.put(publishedItem, nodeSubscriptions);
}
nodeSubscriptions.add(subscription);
}
}
}
// Identify which items should be sent together to the same subscriptions
Map<List<NodeSubscription>, List<PublishedItem>> itemsBySubs =
new HashMap<List<NodeSubscription>, List<PublishedItem>>();
List<PublishedItem> affectedSubscriptions;
for (PublishedItem publishedItem : subsByItem.keySet()) {
affectedSubscriptions = itemsBySubs.get(subsByItem.get(publishedItem));
if (affectedSubscriptions == null) {
itemsBySubs.put(subsByItem.get(publishedItem), Arrays.asList(publishedItem));
}
else {
affectedSubscriptions.add(publishedItem);
}
}
return itemsBySubs;
}
public String toString() { public String toString() {
return super.toString() + " - JID: " + getJID() + " - Affiliation: " + return super.toString() + " - JID: " + getJID() + " - Affiliation: " +
getAffiliation().name(); getAffiliation().name();
......
...@@ -384,6 +384,37 @@ public class NodeSubscription { ...@@ -384,6 +384,37 @@ public class NodeSubscription {
this.savedToDB = savedToDB; this.savedToDB = savedToDB;
} }
/**
* Configures the subscription based on the sent {@link DataForm} included in the IQ
* packet sent by the subscriber. If the subscription was pending of configuration
* then the last published item is going to be sent to the subscriber.<p>
*
* The originalIQ parameter may be <tt>null</tt> when using this API internally. When no
* IQ packet was sent then no IQ result will be sent to the sender. The rest of the
* functionality is the same.
*
* @param originalIQ the IQ packet sent by the subscriber to configure his subscription or
* null when using this API internally.
* @param options the data form containing the new subscription configuration.
*/
public void configure(IQ originalIQ, DataForm options) {
boolean wasUnconfigured = isConfigurationPending();
// Change the subscription configuration based on the completed form
configure(options);
if (originalIQ != null) {
// Return success response
service.send(IQ.createResultIQ(originalIQ));
}
// Send last published item if subscription is now configured (and authorized)
if (wasUnconfigured && !isConfigurationPending() && node.isSendItemSubscribe()) {
PublishedItem lastItem = node.getLastPublishedItem();
if (lastItem != null) {
sendLastPublishedItem(lastItem);
}
}
}
void configure(DataForm options) { void configure(DataForm options) {
List<String> values; List<String> values;
String booleanValue; String booleanValue;
...@@ -473,7 +504,7 @@ public class NodeSubscription { ...@@ -473,7 +504,7 @@ public class NodeSubscription {
* *
* @return data form used by the subscriber to edit the subscription configuration. * @return data form used by the subscriber to edit the subscription configuration.
*/ */
DataForm getConfigurationForm() { public DataForm getConfigurationForm() {
DataForm form = new DataForm(DataForm.Type.form); DataForm form = new DataForm(DataForm.Type.form);
form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.subscription.title")); form.setTitle(LocaleUtils.getLocalizedString("pubsub.form.subscription.title"));
List<String> params = new ArrayList<String>(); List<String> params = new ArrayList<String>();
...@@ -701,7 +732,7 @@ public class NodeSubscription { ...@@ -701,7 +732,7 @@ public class NodeSubscription {
if (((LeafNode) node).isItemRequired()) { if (((LeafNode) node).isItemRequired()) {
item.addAttribute("id", publishedItem.getID()); item.addAttribute("id", publishedItem.getID());
} }
if ((forceToIncludePayload || node.isDeliverPayloads()) && if ((forceToIncludePayload || node.isPayloadDelivered()) &&
publishedItem.getPayload() != null) { publishedItem.getPayload() != null) {
item.add(publishedItem.getPayload().createCopy()); item.add(publishedItem.getPayload().createCopy());
} }
...@@ -736,7 +767,7 @@ public class NodeSubscription { ...@@ -736,7 +767,7 @@ public class NodeSubscription {
if (((LeafNode) node).isItemRequired()) { if (((LeafNode) node).isItemRequired()) {
item.addAttribute("id", publishedItem.getID()); item.addAttribute("id", publishedItem.getID());
} }
if (node.isDeliverPayloads() && publishedItem.getPayload() != null) { if (node.isPayloadDelivered() && publishedItem.getPayload() != null) {
item.add(publishedItem.getPayload().createCopy()); item.add(publishedItem.getPayload().createCopy());
} }
// Add a message body (if required) // Add a message body (if required)
......
...@@ -223,6 +223,10 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di ...@@ -223,6 +223,10 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
return presences.get(subscriber); return presences.get(subscriber);
} }
public PubSubEngine getPubSubEngine() {
return engine;
}
public String getServiceName() { public String getServiceName() {
return serviceName; return serviceName;
} }
...@@ -371,8 +375,6 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di ...@@ -371,8 +375,6 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
JiveGlobals.getBooleanProperty("xmpp.pubsub.default.notify.retract", true)); JiveGlobals.getBooleanProperty("xmpp.pubsub.default.notify.retract", true));
collectionDefaultConfiguration.setPresenceBasedDelivery(JiveGlobals.getBooleanProperty( collectionDefaultConfiguration.setPresenceBasedDelivery(JiveGlobals.getBooleanProperty(
"xmpp.pubsub.default.presenceBasedDelivery", false)); "xmpp.pubsub.default.presenceBasedDelivery", false));
collectionDefaultConfiguration.setSendItemSubscribe(
JiveGlobals.getBooleanProperty("xmpp.pubsub.default.sendItemSubscribe", false));
collectionDefaultConfiguration.setSubscriptionEnabled(JiveGlobals.getBooleanProperty( collectionDefaultConfiguration.setSubscriptionEnabled(JiveGlobals.getBooleanProperty(
"xmpp.pubsub.default.subscriptionEnabled", true)); "xmpp.pubsub.default.subscriptionEnabled", true));
leafDefaultConfiguration.setReplyPolicy(null); leafDefaultConfiguration.setReplyPolicy(null);
...@@ -397,8 +399,6 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di ...@@ -397,8 +399,6 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
rootCollectionNode.addOwner(creatorJID); rootCollectionNode.addOwner(creatorJID);
// Save new root node // Save new root node
rootCollectionNode.saveToDB(); rootCollectionNode.saveToDB();
// Add the new root node to the list of available nodes
addNode(rootCollectionNode);
} }
else { else {
rootCollectionNode = (CollectionNode) getNode(rootNodeID); rootCollectionNode = (CollectionNode) getNode(rootNodeID);
...@@ -419,8 +419,9 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di ...@@ -419,8 +419,9 @@ public class PubSubModule extends BasicModule implements ServerItemsProvider, Di
super.stop(); super.stop();
// Remove the route to this service // Remove the route to this service
routingTable.removeRoute(getAddress()); routingTable.removeRoute(getAddress());
// TODO this // Stop the pubsub engine. This will gives us the chance to
//savePublishedItems(); // save queued items to the database.
engine.shutdown();
} }
public Iterator<DiscoServerItem> getItems() { public Iterator<DiscoServerItem> getItems() {
......
...@@ -154,7 +154,7 @@ public class PubSubPersistenceManager { ...@@ -154,7 +154,7 @@ public class PubSubPersistenceManager {
pstmt.setString(4, StringUtils.dateToMillis(node.getCreationDate())); pstmt.setString(4, StringUtils.dateToMillis(node.getCreationDate()));
pstmt.setString(5, StringUtils.dateToMillis(node.getModificationDate())); pstmt.setString(5, StringUtils.dateToMillis(node.getModificationDate()));
pstmt.setString(6, node.getParent() != null ? node.getParent().getNodeID() : null); pstmt.setString(6, node.getParent() != null ? node.getParent().getNodeID() : null);
pstmt.setInt(7, (node.isDeliverPayloads() ? 1 : 0)); pstmt.setInt(7, (node.isPayloadDelivered() ? 1 : 0));
if (!node.isCollectionNode()) { if (!node.isCollectionNode()) {
pstmt.setInt(8, ((LeafNode) node).getMaxPayloadSize()); pstmt.setInt(8, ((LeafNode) node).getMaxPayloadSize());
pstmt.setInt(9, (((LeafNode) node).isPersistPublishedItems() ? 1 : 0)); pstmt.setInt(9, (((LeafNode) node).isPersistPublishedItems() ? 1 : 0));
...@@ -165,9 +165,9 @@ public class PubSubPersistenceManager { ...@@ -165,9 +165,9 @@ public class PubSubPersistenceManager {
pstmt.setInt(9, 0); pstmt.setInt(9, 0);
pstmt.setInt(10, 0); pstmt.setInt(10, 0);
} }
pstmt.setInt(11, (node.isNotifyConfigChanges() ? 1 : 0)); pstmt.setInt(11, (node.isNotifiedOfConfigChanges() ? 1 : 0));
pstmt.setInt(12, (node.isNotifyDelete() ? 1 : 0)); pstmt.setInt(12, (node.isNotifiedOfDelete() ? 1 : 0));
pstmt.setInt(13, (node.isNotifyRetract() ? 1 : 0)); pstmt.setInt(13, (node.isNotifiedOfRetract() ? 1 : 0));
pstmt.setInt(14, (node.isPresenceBasedDelivery() ? 1 : 0)); pstmt.setInt(14, (node.isPresenceBasedDelivery() ? 1 : 0));
pstmt.setInt(15, (node.isSendItemSubscribe() ? 1 : 0)); pstmt.setInt(15, (node.isSendItemSubscribe() ? 1 : 0));
pstmt.setString(16, node.getPublisherModel().getName()); pstmt.setString(16, node.getPublisherModel().getName());
...@@ -228,7 +228,7 @@ public class PubSubPersistenceManager { ...@@ -228,7 +228,7 @@ public class PubSubPersistenceManager {
pstmt = con.prepareStatement(UPDATE_NODE); pstmt = con.prepareStatement(UPDATE_NODE);
pstmt.setString(1, StringUtils.dateToMillis(node.getModificationDate())); pstmt.setString(1, StringUtils.dateToMillis(node.getModificationDate()));
pstmt.setString(2, node.getParent() != null ? node.getParent().getNodeID() : null); pstmt.setString(2, node.getParent() != null ? node.getParent().getNodeID() : null);
pstmt.setInt(3, (node.isDeliverPayloads() ? 1 : 0)); pstmt.setInt(3, (node.isPayloadDelivered() ? 1 : 0));
if (!node.isCollectionNode()) { if (!node.isCollectionNode()) {
pstmt.setInt(4, ((LeafNode) node).getMaxPayloadSize()); pstmt.setInt(4, ((LeafNode) node).getMaxPayloadSize());
pstmt.setInt(5, (((LeafNode) node).isPersistPublishedItems() ? 1 : 0)); pstmt.setInt(5, (((LeafNode) node).isPersistPublishedItems() ? 1 : 0));
...@@ -239,9 +239,9 @@ public class PubSubPersistenceManager { ...@@ -239,9 +239,9 @@ public class PubSubPersistenceManager {
pstmt.setInt(5, 0); pstmt.setInt(5, 0);
pstmt.setInt(6, 0); pstmt.setInt(6, 0);
} }
pstmt.setInt(7, (node.isNotifyConfigChanges() ? 1 : 0)); pstmt.setInt(7, (node.isNotifiedOfConfigChanges() ? 1 : 0));
pstmt.setInt(8, (node.isNotifyDelete() ? 1 : 0)); pstmt.setInt(8, (node.isNotifiedOfDelete() ? 1 : 0));
pstmt.setInt(9, (node.isNotifyRetract() ? 1 : 0)); pstmt.setInt(9, (node.isNotifiedOfRetract() ? 1 : 0));
pstmt.setInt(10, (node.isPresenceBasedDelivery() ? 1 : 0)); pstmt.setInt(10, (node.isPresenceBasedDelivery() ? 1 : 0));
pstmt.setInt(11, (node.isSendItemSubscribe() ? 1 : 0)); pstmt.setInt(11, (node.isSendItemSubscribe() ? 1 : 0));
pstmt.setString(12, node.getPublisherModel().getName()); pstmt.setString(12, node.getPublisherModel().getName());
...@@ -433,17 +433,17 @@ public class PubSubPersistenceManager { ...@@ -433,17 +433,17 @@ public class PubSubPersistenceManager {
} }
node.setCreationDate(new Date(Long.parseLong(rs.getString(3).trim()))); node.setCreationDate(new Date(Long.parseLong(rs.getString(3).trim())));
node.setModificationDate(new Date(Long.parseLong(rs.getString(4).trim()))); node.setModificationDate(new Date(Long.parseLong(rs.getString(4).trim())));
node.setDeliverPayloads(rs.getInt(6) == 1); node.setPayloadDelivered(rs.getInt(6) == 1);
if (leaf) { if (leaf) {
((LeafNode) node).setMaxPayloadSize(rs.getInt(7)); ((LeafNode) node).setMaxPayloadSize(rs.getInt(7));
((LeafNode) node).setPersistPublishedItems(rs.getInt(8) == 1); ((LeafNode) node).setPersistPublishedItems(rs.getInt(8) == 1);
((LeafNode) node).setMaxPublishedItems(rs.getInt(9)); ((LeafNode) node).setMaxPublishedItems(rs.getInt(9));
((LeafNode) node).setSendItemSubscribe(rs.getInt(14) == 1);
} }
node.setNotifyConfigChanges(rs.getInt(10) == 1); node.setNotifiedOfConfigChanges(rs.getInt(10) == 1);
node.setNotifyDelete(rs.getInt(11) == 1); node.setNotifiedOfDelete(rs.getInt(11) == 1);
node.setNotifyRetract(rs.getInt(12) == 1); node.setNotifiedOfRetract(rs.getInt(12) == 1);
node.setPresenceBasedDelivery(rs.getInt(13) == 1); node.setPresenceBasedDelivery(rs.getInt(13) == 1);
node.setSendItemSubscribe(rs.getInt(14) == 1);
node.setPublisherModel(PublisherModel.valueOf(rs.getString(15))); node.setPublisherModel(PublisherModel.valueOf(rs.getString(15)));
node.setSubscriptionEnabled(rs.getInt(16) == 1); node.setSubscriptionEnabled(rs.getInt(16) == 1);
node.setSubscriptionConfigurationRequired(rs.getInt(17) == 1); node.setSubscriptionConfigurationRequired(rs.getInt(17) == 1);
...@@ -788,14 +788,52 @@ public class PubSubPersistenceManager { ...@@ -788,14 +788,52 @@ public class PubSubPersistenceManager {
} }
} }
/**
* Creates and stores the published item in the database.
*
* @param service the pubsub service that is hosting the node.
* @param item The published item to save.
* @return true if the item was successfully saved to the database.
*/
public static boolean createPublishedItem(PubSubService service, PublishedItem item) {
boolean success = false;
Connection con = null;
PreparedStatement pstmt = null;
try {
con = DbConnectionManager.getConnection();
// Remove the published item from the database
pstmt = con.prepareStatement(ADD_ITEM);
pstmt.setString(1, service.getServiceID());
pstmt.setString(2, item.getNode().getNodeID());
pstmt.setString(3, item.getID());
pstmt.setString(4, item.getPublisher().toString());
pstmt.setString(5, StringUtils.dateToMillis(item.getCreationDate()));
pstmt.setString(6, item.getPayloadXML());
pstmt.executeUpdate();
// Set that the item was successfully saved to the database
success = true;
}
catch (SQLException sqle) {
Log.error(sqle);
}
finally {
try {if (pstmt != null) {pstmt.close();}}
catch (Exception e) {Log.error(e);}
try {if (con != null) {con.close();}}
catch (Exception e) {Log.error(e);}
}
return success;
}
/** /**
* Removes the specified published item from the DB. * Removes the specified published item from the DB.
* *
* @param service the pubsub service that is hosting the node. * @param service the pubsub service that is hosting the node.
* @param node The node where the published item was published.
* @param item The published item to delete. * @param item The published item to delete.
* @return true if the item was successfully deleted from the database.
*/ */
public static void removePublishedItem(PubSubService service, Node node, PublishedItem item) { public static boolean removePublishedItem(PubSubService service, PublishedItem item) {
boolean success = false;
Connection con = null; Connection con = null;
PreparedStatement pstmt = null; PreparedStatement pstmt = null;
try { try {
...@@ -803,9 +841,11 @@ public class PubSubPersistenceManager { ...@@ -803,9 +841,11 @@ public class PubSubPersistenceManager {
// Remove the published item from the database // Remove the published item from the database
pstmt = con.prepareStatement(DELETE_ITEM); pstmt = con.prepareStatement(DELETE_ITEM);
pstmt.setString(1, service.getServiceID()); pstmt.setString(1, service.getServiceID());
pstmt.setString(2, node.getNodeID()); pstmt.setString(2, item.getNode().getNodeID());
pstmt.setString(3, item.getID()); pstmt.setString(3, item.getID());
pstmt.executeUpdate(); pstmt.executeUpdate();
// Set that the item was successfully deleted from the database
success = true;
} }
catch (SQLException sqle) { catch (SQLException sqle) {
Log.error(sqle); Log.error(sqle);
...@@ -816,6 +856,7 @@ public class PubSubPersistenceManager { ...@@ -816,6 +856,7 @@ public class PubSubPersistenceManager {
try {if (con != null) {con.close();}} try {if (con != null) {con.close();}}
catch (Exception e) {Log.error(e);} catch (Exception e) {Log.error(e);}
} }
return success;
} }
/** /**
...@@ -1032,13 +1073,13 @@ public class PubSubPersistenceManager { ...@@ -1032,13 +1073,13 @@ public class PubSubPersistenceManager {
} }
node.setCreationDate(new Date(Long.parseLong(rs.getString(2).trim()))); node.setCreationDate(new Date(Long.parseLong(rs.getString(2).trim())));
node.setModificationDate(new Date(Long.parseLong(rs.getString(3).trim()))); node.setModificationDate(new Date(Long.parseLong(rs.getString(3).trim())));
node.setDeliverPayloads(rs.getInt(5) == 1); node.setPayloadDelivered(rs.getInt(5) == 1);
node.setMaxPayloadSize(rs.getInt(6)); node.setMaxPayloadSize(rs.getInt(6));
node.setPersistPublishedItems(rs.getInt(7) == 1); node.setPersistPublishedItems(rs.getInt(7) == 1);
node.setMaxPublishedItems(rs.getInt(8)); node.setMaxPublishedItems(rs.getInt(8));
node.setNotifyConfigChanges(rs.getInt(9) == 1); node.setNotifiedOfConfigChanges(rs.getInt(9) == 1);
node.setNotifyDelete(rs.getInt(10) == 1); node.setNotifiedOfDelete(rs.getInt(10) == 1);
node.setNotifyRetract(rs.getInt(11) == 1); node.setNotifiedOfRetract(rs.getInt(11) == 1);
node.setPresenceBasedDelivery(rs.getInt(12) == 1); node.setPresenceBasedDelivery(rs.getInt(12) == 1);
node.setSendItemSubscribe(rs.getInt(13) == 1); node.setSendItemSubscribe(rs.getInt(13) == 1);
node.setPublisherModel(Node.PublisherModel.valueOf(rs.getString(14))); node.setPublisherModel(Node.PublisherModel.valueOf(rs.getString(14)));
......
...@@ -175,4 +175,13 @@ public interface PubSubService { ...@@ -175,4 +175,13 @@ public interface PubSubService {
* in RFC 3921. * in RFC 3921.
*/ */
String getShowPresence(JID subscriber); String getShowPresence(JID subscriber);
/**
* Returns the pubsub engine responsible for handling packets sent to the pub-sub service.
* The engine is the actual place where the pubsub magic happens like creating nodes,
* publishing items or subscribing to nodes.
*
* @return the pubsub engine responsible for handling packets sent to the pub-sub service.
*/
PubSubEngine getPubSubEngine();
} }
...@@ -31,7 +31,8 @@ import java.util.Date; ...@@ -31,7 +31,8 @@ import java.util.Date;
public class PublishedItem { public class PublishedItem {
/** /**
* JID of the entity that published the item to the node. * JID of the entity that published the item to the node. This is the full JID
* of the publisher.
*/ */
private JID publisher; private JID publisher;
/** /**
...@@ -110,6 +111,17 @@ public class PublishedItem { ...@@ -110,6 +111,17 @@ public class PublishedItem {
return payload; return payload;
} }
/**
* Returns a textual representation of the payload or <tt>null</tt> if no payload
* was specified with the item.
*
* @return a textual representation of the payload or null if no payload was specified
* with the item.
*/
public String getPayloadXML() {
return payloadXML;
}
/** /**
* Sets the payload included when publishing the item. A published item may or may not * Sets the payload included when publishing the item. A published item may or may not
* have a payload. Transient nodes that are configured to not broadcast payloads may allow * have a payload. Transient nodes that are configured to not broadcast payloads may allow
...@@ -142,4 +154,19 @@ public class PublishedItem { ...@@ -142,4 +154,19 @@ public class PublishedItem {
} }
return payloadXML.contains(keyword); return payloadXML.contains(keyword);
} }
/**
* Returns true if the user that is trying to delete an item is allowed to delete it.
* Only the publisher or node admins (i.e. owners and sysadmins) are allowed to delete items.
*
* @param user the full JID of the user trying to delete the item.
* @return true if the user that is trying to delete an item is allowed to delete it.
*/
public boolean canDelete(JID user) {
if (publisher.equals(user) || publisher.toBareJID().equals(user.toBareJID()) ||
node.isAdmin(user)) {
return true;
}
return false;
}
} }
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
</head>
<body>
<p>Defines policies that define who is allowed to subscribe and retrieve items or policies that
define who is allowed to publish items to nodes. (JEP-0060).</p>
</body>
</html>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment