Example usage for org.dom4j DocumentHelper createElement

List of usage examples for org.dom4j DocumentHelper createElement

Introduction

In this page you can find the example usage for org.dom4j DocumentHelper createElement.

Prototype

public static Element createElement(String name) 

Source Link

Usage

From source file:org.jivesoftware.openfire.muc.spi.MultiUserChatServiceImpl.java

License:Open Source License

public Iterator<Element> getIdentities(String name, String node, JID senderJID) {
    ArrayList<Element> identities = new ArrayList<Element>();
    if (name == null && node == null) {
        // Answer the identity of the MUC service
        Element identity = DocumentHelper.createElement("identity");
        identity.addAttribute("category", "conference");
        identity.addAttribute("name", getDescription());
        identity.addAttribute("type", "text");
        identities.add(identity);//  w  w  w.j  av a 2 s . c o  m

        // TODO: Should internationalize Public Chatroom Search, and make it configurable.
        Element searchId = DocumentHelper.createElement("identity");
        searchId.addAttribute("category", "directory");
        searchId.addAttribute("name", "Public Chatroom Search");
        searchId.addAttribute("type", "chatroom");
        identities.add(searchId);

        if (!extraDiscoIdentities.isEmpty()) {
            identities.addAll(extraDiscoIdentities);
        }
    } else if (name != null && node == null) {
        // Answer the identity of a given room
        MUCRoom room = getChatRoom(name);
        if (room != null) {
            Element identity = DocumentHelper.createElement("identity");
            identity.addAttribute("category", "conference");
            identity.addAttribute("name", room.getNaturalLanguageName());
            identity.addAttribute("type", "text");

            identities.add(identity);
        }
    } else if (name != null && "x-roomuser-item".equals(node)) {
        // Answer reserved nickname for the sender of the disco request in the requested room
        MUCRoom room = getChatRoom(name);
        if (room != null) {
            String reservedNick = room.getReservedNickname(senderJID);
            if (reservedNick != null) {
                Element identity = DocumentHelper.createElement("identity");
                identity.addAttribute("category", "conference");
                identity.addAttribute("name", reservedNick);
                identity.addAttribute("type", "text");

                identities.add(identity);
            }
        }
    }
    return identities.iterator();
}

From source file:org.jivesoftware.openfire.multiplex.MultiplexerPacketHandler.java

License:Open Source License

/**
 * Process IQ packet sent by a connection manager indicating that a new session has
 * been created, should be closed or that a packet was failed to be delivered.
 *
 * @param packet the IQ packet.// w ww .  j ava 2s. c o m
 */
public void handle(Packet packet) {
    if (packet instanceof IQ) {
        IQ iq = (IQ) packet;
        if (iq.getType() == IQ.Type.result) {
            // Do nothing with result packets
        } else if (iq.getType() == IQ.Type.error) {
            // Log the IQ error packet that the connection manager failed to process
            Log.warn("Connection Manager failed to process IQ packet: " + packet.toXML());
        } else if (iq.getType() == IQ.Type.set) {
            Element child = iq.getChildElement();
            String streamID = child.attributeValue("id");
            if (streamID == null) {
                // No stream ID was included so return a bad_request error
                Element extraError = DocumentHelper.createElement(
                        QName.get("id-required", "http://jabber.org/protocol/connectionmanager#errors"));
                sendErrorPacket(iq, PacketError.Condition.bad_request, extraError);
            } else if ("session".equals(child.getName())) {
                Element create = child.element("create");
                if (create != null) {
                    // Get the InetAddress of the client
                    Element hostElement = create.element("host");
                    String hostName = hostElement != null ? hostElement.attributeValue("name") : null;
                    String hostAddress = hostElement != null ? hostElement.attributeValue("address") : null;
                    // Connection Manager wants to create a Client Session
                    boolean created = multiplexerManager.createClientSession(connectionManagerDomain, streamID,
                            hostName, hostAddress);
                    if (created) {
                        sendResultPacket(iq);
                    } else {
                        // Send error to CM. The CM should close the new-borned connection
                        sendErrorPacket(iq, PacketError.Condition.not_allowed, null);
                    }
                } else {
                    ClientSession session = multiplexerManager.getClientSession(connectionManagerDomain,
                            streamID);
                    if (session == null) {
                        // Specified Client Session does not exist
                        sendErrorPacket(iq, PacketError.Condition.item_not_found, null);
                    } else if (child.element("close") != null) {
                        // Connection Manager wants to close a Client Session
                        multiplexerManager.closeClientSession(connectionManagerDomain, streamID);
                        sendResultPacket(iq);
                    } else if (child.element("failed") != null) {
                        // Connection Manager failed to deliver a message
                        // Connection Manager wrapped a packet from a Client Session.
                        List wrappedElements = child.element("failed").elements();
                        if (wrappedElements.size() != 1) {
                            // Wrapper element is wrapping 0 or many items
                            Element extraError = DocumentHelper.createElement(QName.get("invalid-payload",
                                    "http://jabber.org/protocol/connectionmanager#errors"));
                            sendErrorPacket(iq, PacketError.Condition.bad_request, extraError);
                        } else {
                            Element wrappedElement = (Element) wrappedElements.get(0);
                            String tag = wrappedElement.getName();
                            if ("message".equals(tag)) {
                                XMPPServer.getInstance().getOfflineMessageStrategy()
                                        .storeOffline(new Message(wrappedElement));
                                sendResultPacket(iq);
                            } else {
                                Element extraError = DocumentHelper.createElement(QName.get("unknown-stanza",
                                        "http://jabber.org/protocol/connectionmanager#errors"));
                                sendErrorPacket(iq, PacketError.Condition.bad_request, extraError);
                            }
                        }
                    } else {
                        // Unknown IQ packet received so return error to sender
                        sendErrorPacket(iq, PacketError.Condition.bad_request, null);
                    }
                }
            } else {
                // Unknown IQ packet received so return error to sender
                sendErrorPacket(iq, PacketError.Condition.bad_request, null);
            }
        } else {
            // Unknown IQ packet received so return error to sender
            sendErrorPacket(iq, PacketError.Condition.bad_request, null);
        }
    }
}

From source file:org.jivesoftware.openfire.multiplex.MultiplexerPacketHandler.java

License:Open Source License

/**
 * Processes a route packet that is wrapping a stanza sent by a client that is connected
 * to the connection manager./*from   www  . jav  a 2 s .  com*/
 *
 * @param route the route packet.
 */
public void route(Route route) {
    String streamID = route.getStreamID();
    if (streamID == null) {
        // No stream ID was included so return a bad_request error
        Element extraError = DocumentHelper
                .createElement(QName.get("id-required", "http://jabber.org/protocol/connectionmanager#errors"));
        sendErrorPacket(route, PacketError.Condition.bad_request, extraError);
    }
    LocalClientSession session = multiplexerManager.getClientSession(connectionManagerDomain, streamID);
    if (session == null) {
        // Specified Client Session does not exist
        sendErrorPacket(route, PacketError.Condition.item_not_found, null);
        return;
    }

    SessionPacketRouter router = new SessionPacketRouter(session);
    // Connection Manager already validate JIDs so just skip this expensive operation
    router.setSkipJIDValidation(true);
    try {
        router.route(route.getChildElement());
    } catch (UnknownStanzaException use) {
        Element extraError = DocumentHelper.createElement(
                QName.get("unknown-stanza", "http://jabber.org/protocol/connectionmanager#errors"));
        sendErrorPacket(route, PacketError.Condition.bad_request, extraError);
    } catch (Exception e) {
        Log.error("Error processing wrapped packet: " + route.getChildElement().asXML(), e);
        sendErrorPacket(route, PacketError.Condition.internal_server_error, null);
    }
}

From source file:org.jivesoftware.openfire.net.SASLAuthentication.java

License:Open Source License

public static Element getSASLMechanismsElement(Session session) {
    if (!(session instanceof ClientSession) && !(session instanceof IncomingServerSession)) {
        return null;
    }//from w ww .ja  v  a2 s .  c o m

    Element mechs = DocumentHelper
            .createElement(new QName("mechanisms", new Namespace("", "urn:ietf:params:xml:ns:xmpp-sasl")));
    if (session instanceof LocalIncomingServerSession) {
        // Server connections don't follow the same rules as clients
        if (session.isSecure()) {
            boolean haveTrustedCertificate = false;
            try {
                LocalIncomingServerSession svr = (LocalIncomingServerSession) session;
                X509Certificate trusted = CertificateManager.getEndEntityCertificate(
                        svr.getConnection().getPeerCertificates(), SSLConfig.getKeyStore(),
                        SSLConfig.gets2sTrustStore());
                haveTrustedCertificate = trusted != null;
                if (trusted != null && svr.getDefaultIdentity() != null) {
                    haveTrustedCertificate = verifyCertificate(trusted, svr.getDefaultIdentity());
                }
            } catch (IOException ex) {
                Log.warn(
                        "Exception occurred while trying to determine whether remote certificate is trusted. Treating as untrusted.",
                        ex);
            }
            if (haveTrustedCertificate) {
                // Offer SASL EXTERNAL only if TLS has already been negotiated and the peer has a trusted cert.
                Element mechanism = mechs.addElement("mechanism");
                mechanism.setText("EXTERNAL");
            }
        }
    } else {
        for (String mech : getSupportedMechanisms()) {
            Element mechanism = mechs.addElement("mechanism");
            mechanism.setText(mech);
        }
    }
    return mechs;
}

From source file:org.jivesoftware.openfire.pep.IQPEPHandler.java

License:Open Source License

/**
 * Implements ServerIdentitiesProvider and UserIdentitiesProvider, adding
 * the PEP identity to the respective disco#info results.
 *///from w ww. j  ava 2  s.  c  o  m
public Iterator<Element> getIdentities() {
    ArrayList<Element> identities = new ArrayList<Element>();
    Element identity = DocumentHelper.createElement("identity");
    identity.addAttribute("category", "pubsub");
    identity.addAttribute("type", "pep");
    identities.add(identity);
    return identities.iterator();
}

From source file:org.jivesoftware.openfire.pep.IQPEPHandler.java

License:Open Source License

/**
 * Implements UserItemsProvider, adding PEP related items to a disco#items
 * result./*from w w  w. j  av  a2 s. c  o  m*/
 */
public Iterator<Element> getUserItems(String name, JID senderJID) {
    ArrayList<Element> items = new ArrayList<Element>();

    String recipientJID = XMPPServer.getInstance().createJID(name, null, true).toBareJID();
    PEPService pepService = pepServiceManager.getPEPService(recipientJID);

    if (pepService != null) {
        CollectionNode rootNode = pepService.getRootCollectionNode();

        Element defaultItem = DocumentHelper.createElement("item");
        defaultItem.addAttribute("jid", recipientJID);

        for (Node node : pepService.getNodes()) {
            // Do not include the root node as an item element.
            if (node == rootNode) {
                continue;
            }

            AccessModel accessModel = node.getAccessModel();
            if (accessModel.canAccessItems(node, senderJID, new JID(recipientJID))) {
                Element item = defaultItem.createCopy();
                item.addAttribute("node", node.getNodeID());
                items.add(item);
            }
        }
    }

    return items.iterator();
}

From source file:org.jivesoftware.openfire.pep.PEPService.java

License:Open Source License

public void sendNotification(Node node, Message message, JID recipientJID) {
    message.setTo(recipientJID);/*w  ww . j  ava  2  s.  c o m*/
    message.setFrom(getAddress());
    message.setID(node.getNodeID() + "__" + recipientJID.toBareJID() + "__" + StringUtils.randomString(5));

    // If the recipient subscribed with a bare JID and this PEPService can retrieve
    // presence information for the recipient, collect all of their full JIDs and
    // send the notification to each below.
    Set<JID> recipientFullJIDs = new HashSet<JID>();
    if (XMPPServer.getInstance().isLocal(recipientJID)) {
        if (recipientJID.getResource() == null) {
            for (ClientSession clientSession : SessionManager.getInstance()
                    .getSessions(recipientJID.getNode())) {
                recipientFullJIDs.add(clientSession.getAddress());
            }
        }
    } else {
        // Since recipientJID is not local, try to get presence info from cached known remote
        // presences.

        // TODO: OF-605 the old code depends on a cache that would contain presence state on all (?!) JIDS on all (?!)
        // remote domains. As we cannot depend on this information to be correct (even if we could ensure that this
        // potentially unlimited amount of data would indeed be manageable in the first place), this code was removed.

        recipientFullJIDs.add(recipientJID);
    }

    if (recipientFullJIDs.isEmpty()) {
        router.route(message);
        return;
    }

    for (JID recipientFullJID : recipientFullJIDs) {
        // Include an Extended Stanza Addressing "replyto" extension specifying the publishing
        // resource. However, only include the extension if the receiver has a presence subscription
        // to the service owner.
        try {
            JID publisher = null;

            // Get the ID of the node that had an item published to or retracted from.
            Element itemsElement = message.getElement().element("event").element("items");
            String nodeID = itemsElement.attributeValue("node");

            // Get the ID of the item that was published or retracted.
            String itemID = null;
            Element itemElement = itemsElement.element("item");
            if (itemElement == null) {
                Element retractElement = itemsElement.element("retract");
                if (retractElement != null) {
                    itemID = retractElement.attributeValue("id");
                }
            } else {
                itemID = itemElement.attributeValue("id");
            }

            // Check if the recipientFullJID is interested in notifications for this node.
            // If the recipient has not yet requested any notification filtering, continue and send
            // the notification.
            EntityCapabilities entityCaps = entityCapsManager.getEntityCapabilities(recipientFullJID);
            if (entityCaps != null) {
                if (!entityCaps.containsFeature(nodeID + "+notify")) {
                    return;
                }
            }

            // Get the full JID of the item publisher from the node that was published to.
            // This full JID will be used as the "replyto" address in the addressing extension.
            if (node.isCollectionNode()) {
                for (Node leafNode : node.getNodes()) {
                    if (leafNode.getNodeID().equals(nodeID)) {
                        publisher = leafNode.getPublishedItem(itemID).getPublisher();

                        // Ensure the recipientJID has access to receive notifications for items published to the leaf node.
                        AccessModel accessModel = leafNode.getAccessModel();
                        if (!accessModel.canAccessItems(leafNode, recipientFullJID, publisher)) {
                            return;
                        }

                        break;
                    }
                }
            } else {
                publisher = node.getPublishedItem(itemID).getPublisher();
            }

            // Ensure the recipient is subscribed to the service owner's (publisher's) presence.
            if (canProbePresence(publisher, recipientFullJID)) {
                Element addresses = DocumentHelper
                        .createElement(QName.get("addresses", "http://jabber.org/protocol/address"));
                Element address = addresses.addElement("address");
                address.addAttribute("type", "replyto");
                address.addAttribute("jid", publisher.toString());

                Message extendedMessage = message.createCopy();
                extendedMessage.addExtension(new PacketExtension(addresses));

                extendedMessage.setTo(recipientFullJID);
                router.route(extendedMessage);
            }
        } catch (IndexOutOfBoundsException e) {
            // Do not add addressing extension to message.
        } catch (UserNotFoundException e) {
            // Do not add addressing extension to message.
            router.route(message);
        } catch (NullPointerException e) {
            try {
                if (canProbePresence(getAddress(), recipientFullJID)) {
                    message.setTo(recipientFullJID);
                }
            } catch (UserNotFoundException e1) {
                // Do nothing
            }
            router.route(message);
        }
    }
}

From source file:org.jivesoftware.openfire.plugin.SearchPlugin.java

License:Open Source License

/**
 * Processes an IQ stanza of type 'get', which in the context of 'Jabber Search' is a request for available search fields.
 * /*from  w ww . j av a  2  s .c o m*/
 * @param packet
 *            An IQ stanza of type 'get'
 * @return A result IQ stanza that contains the possbile search fields.
 */
private IQ processGetPacket(IQ packet) {
    if (!packet.getType().equals(IQ.Type.get)) {
        throw new IllegalArgumentException("This method only accepts 'get' typed IQ stanzas as an argument.");
    }
    IQ replyPacket = IQ.createResultIQ(packet);

    Element queryResult = DocumentHelper.createElement(QName.get("query", NAMESPACE_JABBER_IQ_SEARCH));

    String instructions = LocaleUtils.getLocalizedString("advance.user.search.details", "search");

    // non-data form
    queryResult.addElement("instructions").addText(instructions);
    queryResult.addElement("first");
    queryResult.addElement("last");
    queryResult.addElement("nick");
    queryResult.addElement("email");

    DataForm searchForm = new DataForm(DataForm.Type.form);
    searchForm.setTitle(LocaleUtils.getLocalizedString("advance.user.search.title", "search"));
    searchForm.addInstruction(instructions);

    searchForm.addField("FORM_TYPE", null, FormField.Type.hidden).addValue(NAMESPACE_JABBER_IQ_SEARCH);

    searchForm.addField("search", LocaleUtils.getLocalizedString("advance.user.search.search", "search"),
            FormField.Type.text_single).setRequired(true);

    for (String searchField : getFilteredSearchFields()) {
        final FormField field = searchForm.addField();
        field.setVariable(searchField);
        field.setType(FormField.Type.boolean_type);
        field.addValue("1");
        field.setLabel(
                LocaleUtils.getLocalizedString("advance.user.search." + searchField.toLowerCase(), "search"));
        field.setRequired(false);
    }

    queryResult.add(searchForm.getElement());
    replyPacket.setChildElement(queryResult);

    return replyPacket;
}

From source file:org.jivesoftware.openfire.pubsub.PubSubEngine.java

License:Open Source License

/**
 * Handles IQ packets sent to the pubsub service. Requests of disco#info and disco#items
 * are not being handled by the engine. Instead the service itself should handle disco packets.
 *
 * @param service the PubSub service this action is to be performed for.
 * @param iq the IQ packet sent to the pubsub service.
 * @return true if the IQ packet was handled by the engine.
 *///ww w. ja  va  2 s  .co m
public boolean process(PubSubService service, IQ iq) {
    // Ignore IQs of type ERROR or RESULT
    if (IQ.Type.error == iq.getType() || IQ.Type.result == iq.getType()) {
        return true;
    }
    Element childElement = iq.getChildElement();
    String namespace = null;

    if (childElement != null) {
        namespace = childElement.getNamespaceURI();
    }
    if ("http://jabber.org/protocol/pubsub".equals(namespace)) {
        Element action = childElement.element("publish");
        if (action != null) {
            // Entity publishes an item
            publishItemsToNode(service, iq, action);
            return true;
        }
        action = childElement.element("subscribe");
        if (action != null) {
            // Entity subscribes to a node
            subscribeNode(service, iq, childElement, action);
            return true;
        }
        action = childElement.element("options");
        if (action != null) {
            if (IQ.Type.get == iq.getType()) {
                // Subscriber requests subscription options form
                getSubscriptionConfiguration(service, iq, childElement, action);
            } else {
                // Subscriber submits completed options form
                configureSubscription(service, iq, action);
            }
            return true;
        }
        action = childElement.element("create");
        if (action != null) {
            // Entity is requesting to create a new node
            createNode(service, iq, childElement, action);
            return true;
        }
        action = childElement.element("unsubscribe");
        if (action != null) {
            // Entity unsubscribes from a node
            unsubscribeNode(service, iq, action);
            return true;
        }
        action = childElement.element("subscriptions");
        if (action != null) {
            // Entity requests all current subscriptions
            getSubscriptions(service, iq, childElement);
            return true;
        }
        action = childElement.element("affiliations");
        if (action != null) {
            // Entity requests all current affiliations
            getAffiliations(service, iq, childElement);
            return true;
        }
        action = childElement.element("items");
        if (action != null) {
            // Subscriber requests all active items
            getPublishedItems(service, iq, action);
            return true;
        }
        action = childElement.element("retract");
        if (action != null) {
            // Entity deletes an item
            deleteItems(service, iq, action);
            return true;
        }
        // Unknown action requested
        sendErrorPacket(iq, PacketError.Condition.bad_request, null);
        return true;
    } else if ("http://jabber.org/protocol/pubsub#owner".equals(namespace)) {
        Element action = childElement.element("configure");
        if (action != null) {
            String nodeID = action.attributeValue("node");
            if (nodeID == null) {
                // if user is not sysadmin then return nodeid-required error
                if (!service.isServiceAdmin(iq.getFrom()) || !service.isCollectionNodesSupported()) {
                    // Configure elements must have a node attribute so answer an error
                    Element pubsubError = DocumentHelper.createElement(
                            QName.get("nodeid-required", "http://jabber.org/protocol/pubsub#errors"));
                    sendErrorPacket(iq, PacketError.Condition.bad_request, pubsubError);
                    return true;
                } else {
                    // Sysadmin is trying to configure root collection node
                    nodeID = service.getRootCollectionNode().getNodeID();
                }
            }
            if (IQ.Type.get == iq.getType()) {
                // Owner requests configuration form of a node
                getNodeConfiguration(service, iq, childElement, nodeID);
            } else {
                // Owner submits or cancels node configuration form
                configureNode(service, iq, action, nodeID);
            }
            return true;
        }
        action = childElement.element("default");
        if (action != null) {
            // Owner requests default configuration options for
            // leaf or collection nodes
            getDefaultNodeConfiguration(service, iq, childElement, action);
            return true;
        }
        action = childElement.element("delete");
        if (action != null) {
            // Owner deletes a node
            deleteNode(service, iq, action);
            return true;
        }
        action = childElement.element("subscriptions");
        if (action != null) {
            if (IQ.Type.get == iq.getType()) {
                // Owner requests all affiliated entities
                getNodeSubscriptions(service, iq, action);
            } else {
                modifyNodeSubscriptions(service, iq, action);
            }
            return true;
        }
        action = childElement.element("affiliations");
        if (action != null) {
            if (IQ.Type.get == iq.getType()) {
                // Owner requests all affiliated entities
                getNodeAffiliations(service, iq, action);
            } else {
                modifyNodeAffiliations(service, iq, action);
            }
            return true;
        }
        action = childElement.element("purge");
        if (action != null) {
            // Owner purges items from a node
            purgeNode(service, iq, action);
            return true;
        }
        // Unknown action requested so return error to sender
        sendErrorPacket(iq, PacketError.Condition.bad_request, null);
        return true;
    } else if ("http://jabber.org/protocol/commands".equals(namespace)) {
        // Process ad-hoc command
        IQ reply = service.getManager().process(iq);
        router.route(reply);
        return true;
    }
    return false;
}

From source file:org.jivesoftware.openfire.pubsub.PubSubEngine.java

License:Open Source License

private void publishItemsToNode(PubSubService service, IQ iq, Element publishElement) {
    String nodeID = publishElement.attributeValue("node");
    Node node;//from   ww w . j  a v a 2 s. c o  m

    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;
    } else {
        // Look for the specified node
        node = service.getNode(nodeID);
        if (node == null) {
            if (service instanceof PEPService && service.isServiceAdmin(owner)) {
                // If it is a PEP service & publisher is service owner -
                // auto create nodes.
                Element childElement = iq.getChildElement();
                Element createElement = publishElement.element("publish");
                CreateNodeResponse response = createNodeHelper(service, iq, childElement, createElement);

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

    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 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;
    }
    // Check that no item was included if node doesn't persist items and doesn't
    // 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<Element>();
    List entries;
    Element payload;
    while (itemElements.hasNext()) {
        Element item = (Element) itemElements.next();
        entries = item.elements();
        payload = entries.isEmpty() ? null : (Element) entries.get(0);
        // Check that a payload was included if node is configured to include payload
        // 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);
}