/** * Returns true if events in general can be sent. This method checks basic conditions common to * all type of event notifications (e.g. item was published, node configuration has changed, new * child node was added to collection node, etc.). * * @return true if events in general can be sent. */ private boolean canSendEvents() { // Check if the subscription is active if (!isActive()) { return false; } // Check if delivery of notifications is disabled if (!shouldDeliverNotifications()) { return false; } // Check if delivery is subject to presence-based policy if (!getPresenceStates().isEmpty()) { Collection<String> shows = service.getShowPresences(jid); if (shows.isEmpty() || Collections.disjoint(getPresenceStates(), shows)) { return false; } } // Check if node is only sending events when user is online if (node.isPresenceBasedDelivery()) { // Check that user is online if (service.getShowPresences(jid).isEmpty()) { return false; } } return true; }
/** * Sends an request to authorize the pending subscription to the specified owner. * * @param owner the JID of the user that will get the authorization request. */ public void sendAuthorizationRequest(JID owner) { Message authRequest = new Message(); authRequest.addExtension(node.getAuthRequestForm(this)); authRequest.setTo(owner); authRequest.setFrom(service.getAddress()); // Send authentication request to node owners service.send(authRequest); }
/** * Sends an event notification for the last published item to the subscriber. If the subscription * has not yet been authorized or is pending to be configured then no notification is going to be * sent. * * <p>Depending on the subscription configuration the event notification may or may not have a * payload, may not be sent if a keyword (i.e. filter) was defined and it was not matched. * * @param publishedItem the last item that was published to the node. */ void sendLastPublishedItem(PublishedItem publishedItem) { // Check if the published item can be sent to the subscriber if (!canSendPublicationEvent(publishedItem.getNode(), publishedItem)) { return; } // Send event notification to the subscriber Message notification = new Message(); Element event = notification.getElement().addElement("event", "http://jabber.org/protocol/pubsub#event"); Element items = event.addElement("items"); items.addAttribute("node", node.getNodeID()); Element item = items.addElement("item"); if (((LeafNode) node).isItemRequired()) { item.addAttribute("id", publishedItem.getID()); } if (node.isPayloadDelivered() && publishedItem.getPayload() != null) { item.add(publishedItem.getPayload().createCopy()); } // Add a message body (if required) if (isIncludingBody()) { notification.setBody(LocaleUtils.getLocalizedString("pubsub.notification.message.body")); } // Include date when published item was created notification .getElement() .addElement("delay", "urn:xmpp:delay") .addAttribute("stamp", fastDateFormat.format(publishedItem.getCreationDate())); // Send the event notification to the subscriber service.sendNotification(node, notification, jid); }
/** * 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)); } if (wasUnconfigured) { // If subscription is pending then send notification to node owners // asking to approve the now configured subscription if (isAuthorizationPending()) { sendAuthorizationRequest(); } // Send last published item (if node is leaf node and subscription status is ok) if (node.isSendItemSubscribe() && isActive()) { PublishedItem lastItem = node.getLastPublishedItem(); if (lastItem != null) { sendLastPublishedItem(lastItem); } } } }
/** * Sends the current subscription status to the user that tried to create a subscription to the * node. The subscription status is sent to the subsciber after the subscription was created or if * the subscriber tries to subscribe many times and the node does not support multpiple * subscriptions. * * @param originalRequest the IQ packet sent by the subscriber to create the subscription. */ void sendSubscriptionState(IQ originalRequest) { IQ result = IQ.createResultIQ(originalRequest); Element child = result.setChildElement("pubsub", "http://jabber.org/protocol/pubsub"); Element entity = child.addElement("subscription"); if (!node.isRootCollectionNode()) { entity.addAttribute("node", node.getNodeID()); } entity.addAttribute("jid", getJID().toString()); if (node.isMultipleSubscriptionsEnabled()) { entity.addAttribute("subid", getID()); } entity.addAttribute("subscription", getState().name()); Element subscribeOptions = entity.addElement("subscribe-options"); if (node.isSubscriptionConfigurationRequired() && isConfigurationPending()) { subscribeOptions.addElement("required"); } // Send the result service.send(result); }
@JmsListener(destination = "simpleTopic") public void readMessage(String message) { pubSubService.processText(1, message); }
/** * Sends an request to authorize the pending subscription to all owners. The first answer sent by * a owner will be processed. Rest of the answers will be discarded. */ public void sendAuthorizationRequest() { Message authRequest = new Message(); authRequest.addExtension(node.getAuthRequestForm(this)); // Send authentication request to node owners service.broadcast(node, authRequest, node.getOwners()); }
/** * Returns true if the specified user is allowed to modify or cancel the subscription. Users that * are allowed to modify/cancel the subscription are: the entity that is recieving the * notifications, the owner of the subscriptions or sysadmins of the pubsub service. * * @param user the user that is trying to cancel the subscription. * @return true if the specified user is allowed to modify or cancel the subscription. */ boolean canModify(JID user) { return user.equals(getJID()) || user.equals(getOwner()) || service.isServiceAdmin(user); }
void configure(DataForm options) { List<String> values; String booleanValue; boolean wasUsingPresence = !presenceStates.isEmpty(); // Remove this field from the form options.removeField("FORM_TYPE"); // Process and remove specific collection node fields FormField collectionField = options.getField("pubsub#subscription_type"); if (collectionField != null) { values = collectionField.getValues(); if (values.size() > 0) { type = Type.valueOf(values.get(0)); } options.removeField("pubsub#subscription_type"); } collectionField = options.getField("pubsub#subscription_depth"); if (collectionField != null) { values = collectionField.getValues(); depth = "all".equals(values.get(0)) ? 0 : 1; options.removeField("pubsub#subscription_depth"); } // If there are more fields in the form then process them and set that // the subscription has been configured for (FormField field : options.getFields()) { boolean fieldExists = true; if ("pubsub#deliver".equals(field.getVariable())) { values = field.getValues(); booleanValue = (values.size() > 0 ? values.get(0) : "1"); deliverNotifications = "1".equals(booleanValue); } else if ("pubsub#digest".equals(field.getVariable())) { values = field.getValues(); booleanValue = (values.size() > 0 ? values.get(0) : "1"); usingDigest = "1".equals(booleanValue); } else if ("pubsub#digest_frequency".equals(field.getVariable())) { values = field.getValues(); digestFrequency = values.size() > 0 ? Integer.parseInt(values.get(0)) : 86400000; } else if ("pubsub#expire".equals(field.getVariable())) { values = field.getValues(); synchronized (dateFormat) { try { expire = dateFormat.parse(values.get(0)); } catch (ParseException e) { Log.error("Error parsing date", e); } } } else if ("pubsub#include_body".equals(field.getVariable())) { values = field.getValues(); booleanValue = (values.size() > 0 ? values.get(0) : "1"); includingBody = "1".equals(booleanValue); } else if ("pubsub#show-values".equals(field.getVariable())) { // Get the new list of presence states for which an entity wants to // receive notifications presenceStates = new ArrayList<String>(); for (String value : field.getValues()) { try { presenceStates.add(value); } catch (Exception e) { // Do nothing } } } else if ("x-pubsub#keywords".equals(field.getVariable())) { values = field.getValues(); keyword = values.isEmpty() ? null : values.get(0); } else { fieldExists = false; } if (fieldExists) { // Subscription has been configured so set the next state if (node.getAccessModel().isAuthorizationRequired() && !node.isAdmin(owner)) { state = State.pending; } else { state = State.subscribed; } } } if (savedToDB) { // Update the subscription in the backend store PubSubPersistenceManager.saveSubscription(service, node, this, false); } // Check if the service needs to subscribe or unsubscribe from the owner presence if (!node.isPresenceBasedDelivery() && wasUsingPresence != !presenceStates.isEmpty()) { if (presenceStates.isEmpty()) { service.presenceSubscriptionNotRequired(node, owner); } else { service.presenceSubscriptionRequired(node, owner); } } }