Source Code Cross Referenced for PubSubEngine.java in  » Net » openfire » org » jivesoftware » openfire » pubsub » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Net » openfire » org.jivesoftware.openfire.pubsub 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * $RCSfile: $
0003:         * $Revision: $
0004:         * $Date: $
0005:         *
0006:         * Copyright (C) 2006 Jive Software. All rights reserved.
0007:         *
0008:         * This software is published under the terms of the GNU Public License (GPL),
0009:         * a copy of which is included in this distribution.
0010:         */package org.jivesoftware.openfire.pubsub;
0011:
0012:        import org.dom4j.DocumentHelper;
0013:        import org.dom4j.Element;
0014:        import org.dom4j.QName;
0015:        import org.jivesoftware.openfire.PacketRouter;
0016:        import org.jivesoftware.openfire.XMPPServer;
0017:        import org.jivesoftware.openfire.XMPPServerListener;
0018:        import org.jivesoftware.openfire.pubsub.models.AccessModel;
0019:        import org.jivesoftware.openfire.user.UserManager;
0020:        import org.jivesoftware.util.Log;
0021:        import org.jivesoftware.util.StringUtils;
0022:        import org.xmpp.forms.DataForm;
0023:        import org.xmpp.forms.FormField;
0024:        import org.xmpp.packet.*;
0025:
0026:        import java.util.*;
0027:        import java.util.concurrent.ConcurrentHashMap;
0028:
0029:        /**
0030:         * A PubSubEngine is responsible for handling packets sent to a pub-sub service.
0031:         *
0032:         * @author Matt Tucker
0033:         */
0034:        public class PubSubEngine {
0035:
0036:            /**
0037:             * The packet router for the server.
0038:             */
0039:            private PacketRouter router = null;
0040:
0041:            public PubSubEngine(PacketRouter router) {
0042:                this .router = router;
0043:            }
0044:
0045:            /**
0046:             * Handles IQ packets sent to the pubsub service. Requests of disco#info and disco#items
0047:             * are not being handled by the engine. Instead the service itself should handle disco packets.
0048:             *
0049:             * @param service the PubSub service this action is to be performed for.
0050:             * @param iq the IQ packet sent to the pubsub service.
0051:             * @return true if the IQ packet was handled by the engine.
0052:             */
0053:            public boolean process(PubSubService service, IQ iq) {
0054:                // Ignore IQs of type ERROR or RESULT
0055:                if (IQ.Type.error == iq.getType()
0056:                        || IQ.Type.result == iq.getType()) {
0057:                    return true;
0058:                }
0059:                Element childElement = iq.getChildElement();
0060:                String namespace = null;
0061:
0062:                if (childElement != null) {
0063:                    namespace = childElement.getNamespaceURI();
0064:                }
0065:                if ("http://jabber.org/protocol/pubsub".equals(namespace)) {
0066:                    Element action = childElement.element("publish");
0067:                    if (action != null) {
0068:                        // Entity publishes an item
0069:                        publishItemsToNode(service, iq, action);
0070:                        return true;
0071:                    }
0072:                    action = childElement.element("subscribe");
0073:                    if (action != null) {
0074:                        // Entity subscribes to a node
0075:                        subscribeNode(service, iq, childElement, action);
0076:                        return true;
0077:                    }
0078:                    action = childElement.element("options");
0079:                    if (action != null) {
0080:                        if (IQ.Type.get == iq.getType()) {
0081:                            // Subscriber requests subscription options form
0082:                            getSubscriptionConfiguration(service, iq,
0083:                                    childElement, action);
0084:                        } else {
0085:                            // Subscriber submits completed options form
0086:                            configureSubscription(service, iq, action);
0087:                        }
0088:                        return true;
0089:                    }
0090:                    action = childElement.element("create");
0091:                    if (action != null) {
0092:                        // Entity is requesting to create a new node
0093:                        createNode(service, iq, childElement, action);
0094:                        return true;
0095:                    }
0096:                    action = childElement.element("unsubscribe");
0097:                    if (action != null) {
0098:                        // Entity unsubscribes from a node
0099:                        unsubscribeNode(service, iq, action);
0100:                        return true;
0101:                    }
0102:                    action = childElement.element("subscriptions");
0103:                    if (action != null) {
0104:                        // Entity requests all current subscriptions
0105:                        getSubscriptions(service, iq, childElement);
0106:                        return true;
0107:                    }
0108:                    action = childElement.element("affiliations");
0109:                    if (action != null) {
0110:                        // Entity requests all current affiliations
0111:                        getAffiliations(service, iq, childElement);
0112:                        return true;
0113:                    }
0114:                    action = childElement.element("items");
0115:                    if (action != null) {
0116:                        // Subscriber requests all active items
0117:                        getPublishedItems(service, iq, action);
0118:                        return true;
0119:                    }
0120:                    action = childElement.element("retract");
0121:                    if (action != null) {
0122:                        // Entity deletes an item
0123:                        deleteItems(service, iq, action);
0124:                        return true;
0125:                    }
0126:                    // Unknown action requested
0127:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
0128:                    return true;
0129:                } else if ("http://jabber.org/protocol/pubsub#owner"
0130:                        .equals(namespace)) {
0131:                    Element action = childElement.element("configure");
0132:                    if (action != null) {
0133:                        String nodeID = action.attributeValue("node");
0134:                        if (nodeID == null) {
0135:                            // if user is not sysadmin then return nodeid-required error
0136:                            if (!service.isServiceAdmin(iq.getFrom())
0137:                                    || !service.isCollectionNodesSupported()) {
0138:                                // Configure elements must have a node attribute so answer an error
0139:                                Element pubsubError = DocumentHelper
0140:                                        .createElement(QName
0141:                                                .get("nodeid-required",
0142:                                                        "http://jabber.org/protocol/pubsub#errors"));
0143:                                sendErrorPacket(iq,
0144:                                        PacketError.Condition.bad_request,
0145:                                        pubsubError);
0146:                                return true;
0147:                            } else {
0148:                                // Sysadmin is trying to configure root collection node
0149:                                nodeID = service.getRootCollectionNode()
0150:                                        .getNodeID();
0151:                            }
0152:                        }
0153:                        if (IQ.Type.get == iq.getType()) {
0154:                            // Owner requests configuration form of a node
0155:                            getNodeConfiguration(service, iq, childElement,
0156:                                    nodeID);
0157:                        } else {
0158:                            // Owner submits or cancels node configuration form
0159:                            configureNode(service, iq, action, nodeID);
0160:                        }
0161:                        return true;
0162:                    }
0163:                    action = childElement.element("default");
0164:                    if (action != null) {
0165:                        // Owner requests default configuration options for
0166:                        // leaf or collection nodes
0167:                        getDefaultNodeConfiguration(service, iq, childElement,
0168:                                action);
0169:                        return true;
0170:                    }
0171:                    action = childElement.element("delete");
0172:                    if (action != null) {
0173:                        // Owner deletes a node
0174:                        deleteNode(service, iq, action);
0175:                        return true;
0176:                    }
0177:                    action = childElement.element("subscriptions");
0178:                    if (action != null) {
0179:                        if (IQ.Type.get == iq.getType()) {
0180:                            // Owner requests all affiliated entities
0181:                            getNodeSubscriptions(service, iq, action);
0182:                        } else {
0183:                            modifyNodeSubscriptions(service, iq, action);
0184:                        }
0185:                        return true;
0186:                    }
0187:                    action = childElement.element("affiliations");
0188:                    if (action != null) {
0189:                        if (IQ.Type.get == iq.getType()) {
0190:                            // Owner requests all affiliated entities
0191:                            getNodeAffiliations(service, iq, action);
0192:                        } else {
0193:                            modifyNodeAffiliations(service, iq, action);
0194:                        }
0195:                        return true;
0196:                    }
0197:                    action = childElement.element("purge");
0198:                    if (action != null) {
0199:                        // Owner purges items from a node
0200:                        purgeNode(service, iq, action);
0201:                        return true;
0202:                    }
0203:                    // Unknown action requested so return error to sender
0204:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
0205:                    return true;
0206:                } else if ("http://jabber.org/protocol/commands"
0207:                        .equals(namespace)) {
0208:                    // Process ad-hoc command
0209:                    IQ reply = service.getManager().process(iq);
0210:                    router.route(reply);
0211:                    return true;
0212:                }
0213:                return false;
0214:            }
0215:
0216:            /**
0217:             * Handles Presence packets sent to the pubsub service. Only process available and not
0218:             * available presences.
0219:             *
0220:             * @param service the PubSub service this action is to be performed for.
0221:             * @param presence the Presence packet sent to the pubsub service.
0222:             */
0223:            public void process(PubSubService service, Presence presence) {
0224:                if (presence.isAvailable()) {
0225:                    JID subscriber = presence.getFrom();
0226:                    Map<String, String> fullPresences = service
0227:                            .getBarePresences().get(subscriber.toBareJID());
0228:                    if (fullPresences == null) {
0229:                        synchronized (subscriber.toBareJID().intern()) {
0230:                            fullPresences = service.getBarePresences().get(
0231:                                    subscriber.toBareJID());
0232:                            if (fullPresences == null) {
0233:                                fullPresences = new ConcurrentHashMap<String, String>();
0234:                                service.getBarePresences().put(
0235:                                        subscriber.toBareJID(), fullPresences);
0236:                            }
0237:                        }
0238:                    }
0239:                    Presence.Show show = presence.getShow();
0240:                    fullPresences.put(subscriber.toString(),
0241:                            show == null ? "online" : show.name());
0242:                } else if (presence.getType() == Presence.Type.unavailable) {
0243:                    JID subscriber = presence.getFrom();
0244:                    Map<String, String> fullPresences = service
0245:                            .getBarePresences().get(subscriber.toBareJID());
0246:                    if (fullPresences != null) {
0247:                        fullPresences.remove(subscriber.toString());
0248:                        if (fullPresences.isEmpty()) {
0249:                            service.getBarePresences().remove(
0250:                                    subscriber.toBareJID());
0251:                        }
0252:                    }
0253:                }
0254:            }
0255:
0256:            /**
0257:             * Handles Message packets sent to the pubsub service. Messages may be of type error
0258:             * when an event notification was sent to a susbcriber whose address is no longer available.<p>
0259:             *
0260:             * Answers to authorization requests sent to node owners to approve pending subscriptions
0261:             * will also be processed by this method.
0262:             *
0263:             * @param service the PubSub service this action is to be performed for.
0264:             * @param message the Message packet sent to the pubsub service.
0265:             */
0266:            public void process(PubSubService service, Message message) {
0267:                if (message.getType() == Message.Type.error) {
0268:                    // Process Messages of type error to identify possible subscribers that no longer exist
0269:                    if (message.getError().getType() == PacketError.Type.cancel) {
0270:                        // 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
0271:                        JID owner = new JID(message.getFrom().toBareJID());
0272:                        // Terminate the subscription of the entity to all nodes hosted at the service
0273:                        cancelAllSubscriptions(service, owner);
0274:                    } else if (message.getError().getType() == PacketError.Type.auth) {
0275:                        // TODO Queue the message to be sent again later (will retry a few times and
0276:                        // will be discarded when the retry limit is reached)
0277:                    }
0278:                } else if (message.getType() == Message.Type.normal) {
0279:                    // Check that this is an answer to an authorization request
0280:                    DataForm authForm = (DataForm) message.getExtension("x",
0281:                            "jabber:x:data");
0282:                    if (authForm != null
0283:                            && authForm.getType() == DataForm.Type.submit) {
0284:                        String formType = authForm.getField("FORM_TYPE")
0285:                                .getValues().get(0);
0286:                        // Check that completed data form belongs to an authorization request
0287:                        if ("http://jabber.org/protocol/pubsub#subscribe_authorization"
0288:                                .equals(formType)) {
0289:                            // Process the answer to the authorization request
0290:                            processAuthorizationAnswer(service, authForm,
0291:                                    message);
0292:                        }
0293:                    }
0294:                }
0295:            }
0296:
0297:            private void publishItemsToNode(PubSubService service, IQ iq,
0298:                    Element publishElement) {
0299:                String nodeID = publishElement.attributeValue("node");
0300:                Node node;
0301:                if (nodeID == null) {
0302:                    // No node was specified. Return bad_request error
0303:                    Element pubsubError = DocumentHelper
0304:                            .createElement(QName.get("nodeid-required",
0305:                                    "http://jabber.org/protocol/pubsub#errors"));
0306:                    sendErrorPacket(iq, PacketError.Condition.bad_request,
0307:                            pubsubError);
0308:                    return;
0309:                } else {
0310:                    // Look for the specified node
0311:                    node = service.getNode(nodeID);
0312:                    if (node == null) {
0313:                        // Node does not exist. Return item-not-found error
0314:                        sendErrorPacket(iq,
0315:                                PacketError.Condition.item_not_found, null);
0316:                        return;
0317:                    }
0318:                }
0319:
0320:                JID from = iq.getFrom();
0321:                // 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
0322:                JID owner = new JID(from.toBareJID());
0323:                if (!node.getPublisherModel().canPublish(node, owner)
0324:                        && !service.isServiceAdmin(owner)) {
0325:                    // Entity does not have sufficient privileges to publish to node
0326:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
0327:                    return;
0328:                }
0329:
0330:                if (node.isCollectionNode()) {
0331:                    // Node is a collection node. Return feature-not-implemented error
0332:                    Element pubsubError = DocumentHelper
0333:                            .createElement(QName.get("unsupported",
0334:                                    "http://jabber.org/protocol/pubsub#errors"));
0335:                    pubsubError.addAttribute("feature", "publish");
0336:                    sendErrorPacket(iq,
0337:                            PacketError.Condition.feature_not_implemented,
0338:                            pubsubError);
0339:                    return;
0340:                }
0341:
0342:                LeafNode leafNode = (LeafNode) node;
0343:                Iterator itemElements = publishElement.elementIterator("item");
0344:
0345:                // Check that an item was included if node persist items or includes payload
0346:                if (!itemElements.hasNext() && leafNode.isItemRequired()) {
0347:                    Element pubsubError = DocumentHelper
0348:                            .createElement(QName.get("item-required",
0349:                                    "http://jabber.org/protocol/pubsub#errors"));
0350:                    sendErrorPacket(iq, PacketError.Condition.bad_request,
0351:                            pubsubError);
0352:                    return;
0353:                }
0354:                // Check that no item was included if node doesn't persist items and doesn't
0355:                // includes payload
0356:                if (itemElements.hasNext() && !leafNode.isItemRequired()) {
0357:                    Element pubsubError = DocumentHelper
0358:                            .createElement(QName.get("item-forbidden",
0359:                                    "http://jabber.org/protocol/pubsub#errors"));
0360:                    sendErrorPacket(iq, PacketError.Condition.bad_request,
0361:                            pubsubError);
0362:                    return;
0363:                }
0364:                List<Element> items = new ArrayList<Element>();
0365:                List entries;
0366:                Element payload;
0367:                while (itemElements.hasNext()) {
0368:                    Element item = (Element) itemElements.next();
0369:                    entries = item.elements();
0370:                    payload = entries.isEmpty() ? null : (Element) entries
0371:                            .get(0);
0372:                    // Check that a payload was included if node is configured to include payload
0373:                    // in notifications
0374:                    if (payload == null && leafNode.isPayloadDelivered()) {
0375:                        Element pubsubError = DocumentHelper
0376:                                .createElement(QName
0377:                                        .get("payload-required",
0378:                                                "http://jabber.org/protocol/pubsub#errors"));
0379:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0380:                                pubsubError);
0381:                        return;
0382:                    }
0383:                    // Check that the payload (if any) contains only one child element
0384:                    if (entries.size() > 1) {
0385:                        Element pubsubError = DocumentHelper
0386:                                .createElement(QName
0387:                                        .get("invalid-payload",
0388:                                                "http://jabber.org/protocol/pubsub#errors"));
0389:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0390:                                pubsubError);
0391:                        return;
0392:                    }
0393:                    items.add(item);
0394:                }
0395:
0396:                // Return success operation
0397:                router.route(IQ.createResultIQ(iq));
0398:                // Publish item and send event notifications to subscribers
0399:                leafNode.publishItems(from, items);
0400:            }
0401:
0402:            private void deleteItems(PubSubService service, IQ iq,
0403:                    Element retractElement) {
0404:                String nodeID = retractElement.attributeValue("node");
0405:                Node node;
0406:                if (nodeID == null) {
0407:                    // No node was specified. Return bad_request error
0408:                    Element pubsubError = DocumentHelper
0409:                            .createElement(QName.get("nodeid-required",
0410:                                    "http://jabber.org/protocol/pubsub#errors"));
0411:                    sendErrorPacket(iq, PacketError.Condition.bad_request,
0412:                            pubsubError);
0413:                    return;
0414:                } else {
0415:                    // Look for the specified node
0416:                    node = service.getNode(nodeID);
0417:                    if (node == null) {
0418:                        // Node does not exist. Return item-not-found error
0419:                        sendErrorPacket(iq,
0420:                                PacketError.Condition.item_not_found, null);
0421:                        return;
0422:                    }
0423:                }
0424:                // Get the items to delete
0425:                Iterator itemElements = retractElement.elementIterator("item");
0426:                if (!itemElements.hasNext()) {
0427:                    Element pubsubError = DocumentHelper
0428:                            .createElement(QName.get("item-required",
0429:                                    "http://jabber.org/protocol/pubsub#errors"));
0430:                    sendErrorPacket(iq, PacketError.Condition.bad_request,
0431:                            pubsubError);
0432:                    return;
0433:                }
0434:
0435:                if (node.isCollectionNode()) {
0436:                    // Cannot delete items from a collection node. Return an error.
0437:                    Element pubsubError = DocumentHelper
0438:                            .createElement(QName.get("unsupported",
0439:                                    "http://jabber.org/protocol/pubsub#errors"));
0440:                    pubsubError.addAttribute("feature", "persistent-items");
0441:                    sendErrorPacket(iq,
0442:                            PacketError.Condition.feature_not_implemented,
0443:                            pubsubError);
0444:                    return;
0445:                }
0446:                LeafNode leafNode = (LeafNode) node;
0447:
0448:                if (!leafNode.isItemRequired()) {
0449:                    // Cannot delete items from a leaf node that doesn't handle itemIDs. Return an error.
0450:                    Element pubsubError = DocumentHelper
0451:                            .createElement(QName.get("unsupported",
0452:                                    "http://jabber.org/protocol/pubsub#errors"));
0453:                    pubsubError.addAttribute("feature", "persistent-items");
0454:                    sendErrorPacket(iq,
0455:                            PacketError.Condition.feature_not_implemented,
0456:                            pubsubError);
0457:                    return;
0458:                }
0459:
0460:                List<PublishedItem> items = new ArrayList<PublishedItem>();
0461:                while (itemElements.hasNext()) {
0462:                    Element itemElement = (Element) itemElements.next();
0463:                    String itemID = itemElement.attributeValue("id");
0464:                    if (itemID != null) {
0465:                        PublishedItem item = node.getPublishedItem(itemID);
0466:                        if (item == null) {
0467:                            // ItemID does not exist. Return item-not-found error
0468:                            sendErrorPacket(iq,
0469:                                    PacketError.Condition.item_not_found, null);
0470:                            return;
0471:                        } else {
0472:                            if (item.canDelete(iq.getFrom())) {
0473:                                items.add(item);
0474:                            } else {
0475:                                // Publisher does not have sufficient privileges to delete this item
0476:                                sendErrorPacket(iq,
0477:                                        PacketError.Condition.forbidden, null);
0478:                                return;
0479:                            }
0480:                        }
0481:                    } else {
0482:                        // No item ID was specified so return a bad_request error
0483:                        Element pubsubError = DocumentHelper
0484:                                .createElement(QName
0485:                                        .get("item-required",
0486:                                                "http://jabber.org/protocol/pubsub#errors"));
0487:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0488:                                pubsubError);
0489:                        return;
0490:                    }
0491:                }
0492:                // Send reply with success
0493:                router.route(IQ.createResultIQ(iq));
0494:                // Delete items and send subscribers a notification
0495:                leafNode.deleteItems(items);
0496:            }
0497:
0498:            private void subscribeNode(PubSubService service, IQ iq,
0499:                    Element childElement, Element subscribeElement) {
0500:                String nodeID = subscribeElement.attributeValue("node");
0501:                Node node;
0502:                if (nodeID == null) {
0503:                    if (service.isCollectionNodesSupported()) {
0504:                        // Entity subscribes to root collection node
0505:                        node = service.getRootCollectionNode();
0506:                    } else {
0507:                        // Service does not have a root collection node so return a nodeid-required error
0508:                        Element pubsubError = DocumentHelper
0509:                                .createElement(QName
0510:                                        .get("nodeid-required",
0511:                                                "http://jabber.org/protocol/pubsub#errors"));
0512:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0513:                                pubsubError);
0514:                        return;
0515:                    }
0516:                } else {
0517:                    // Look for the specified node
0518:                    node = service.getNode(nodeID);
0519:                    if (node == null) {
0520:                        // Node does not exist. Return item-not-found error
0521:                        sendErrorPacket(iq,
0522:                                PacketError.Condition.item_not_found, null);
0523:                        return;
0524:                    }
0525:                }
0526:                // Check if sender and subscriber JIDs match or if a valid "trusted proxy" is being used
0527:                JID from = iq.getFrom();
0528:                JID subscriberJID = new JID(subscribeElement
0529:                        .attributeValue("jid"));
0530:                if (!from.toBareJID().equals(subscriberJID.toBareJID())
0531:                        && !service.isServiceAdmin(from)) {
0532:                    // JIDs do not match and requestor is not a service admin so return an error
0533:                    Element pubsubError = DocumentHelper
0534:                            .createElement(QName.get("invalid-jid",
0535:                                    "http://jabber.org/protocol/pubsub#errors"));
0536:                    sendErrorPacket(iq, PacketError.Condition.bad_request,
0537:                            pubsubError);
0538:                    return;
0539:                }
0540:                // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
0541:                JID owner = new JID(subscriberJID.toBareJID());
0542:                // Check if the node's access model allows the subscription to proceed
0543:                AccessModel accessModel = node.getAccessModel();
0544:                if (!accessModel.canSubscribe(node, owner, subscriberJID)) {
0545:                    sendErrorPacket(iq, accessModel.getSubsriptionError(),
0546:                            accessModel.getSubsriptionErrorDetail());
0547:                    return;
0548:                }
0549:                // Check if the subscriber is an anonymous user
0550:                if (!UserManager.getInstance().isRegisteredUser(subscriberJID)) {
0551:                    // Anonymous users cannot subscribe to the node. Return forbidden error
0552:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
0553:                    return;
0554:                }
0555:                // Check if the subscription owner is a user with outcast affiliation
0556:                NodeAffiliate nodeAffiliate = node.getAffiliate(owner);
0557:                if (nodeAffiliate != null
0558:                        && nodeAffiliate.getAffiliation() == NodeAffiliate.Affiliation.outcast) {
0559:                    // Subscriber is an outcast. Return forbidden error
0560:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
0561:                    return;
0562:                }
0563:                // Check that subscriptions to the node are enabled
0564:                if (!node.isSubscriptionEnabled()
0565:                        && !service.isServiceAdmin(from)) {
0566:                    // Sender is not a sysadmin and subscription is disabled so return an error
0567:                    sendErrorPacket(iq, PacketError.Condition.not_allowed, null);
0568:                    return;
0569:                }
0570:
0571:                // Get any configuration form included in the options element (if any)
0572:                DataForm optionsForm = null;
0573:                Element options = childElement.element("options");
0574:                if (options != null) {
0575:                    Element formElement = options.element(QName.get("x",
0576:                            "jabber:x:data"));
0577:                    if (formElement != null) {
0578:                        optionsForm = new DataForm(formElement);
0579:                    }
0580:                }
0581:
0582:                // If leaf node does not support multiple subscriptions then check whether subscriber is
0583:                // creating another subscription or not
0584:                if (!node.isCollectionNode()
0585:                        && !node.isMultipleSubscriptionsEnabled()) {
0586:                    NodeSubscription existingSubscription = node
0587:                            .getSubscription(subscriberJID);
0588:                    if (existingSubscription != null) {
0589:                        // User is trying to create another subscription so
0590:                        // return current subscription state
0591:                        existingSubscription.sendSubscriptionState(iq);
0592:                        return;
0593:                    }
0594:                }
0595:
0596:                // Check if subscribing twice to a collection node using same subscription type
0597:                if (node.isCollectionNode()) {
0598:                    // By default assume that new subscription is of type node
0599:                    boolean isNodeType = true;
0600:                    if (optionsForm != null) {
0601:                        FormField field = optionsForm
0602:                                .getField("pubsub#subscription_type");
0603:                        if (field != null) {
0604:                            if ("items".equals(field.getValues().get(0))) {
0605:                                isNodeType = false;
0606:                            }
0607:                        }
0608:                    }
0609:                    if (nodeAffiliate != null) {
0610:                        for (NodeSubscription subscription : nodeAffiliate
0611:                                .getSubscriptions()) {
0612:                            if (isNodeType) {
0613:                                // User is requesting a subscription of type "nodes"
0614:                                if (NodeSubscription.Type.nodes == subscription
0615:                                        .getType()) {
0616:                                    // Cannot have 2 subscriptions of the same type. Return conflict error
0617:                                    sendErrorPacket(iq,
0618:                                            PacketError.Condition.conflict,
0619:                                            null);
0620:                                    return;
0621:                                }
0622:                            } else if (!node.isMultipleSubscriptionsEnabled()) {
0623:                                // User is requesting a subscription of type "items" and
0624:                                // multiple subscriptions is not allowed
0625:                                if (NodeSubscription.Type.items == subscription
0626:                                        .getType()) {
0627:                                    // User is trying to create another subscription so
0628:                                    // return current subscription state
0629:                                    subscription.sendSubscriptionState(iq);
0630:                                    return;
0631:                                }
0632:                            }
0633:                        }
0634:                    }
0635:                }
0636:
0637:                // Create a subscription and an affiliation if the subscriber doesn't have one
0638:                node.createSubscription(iq, owner, subscriberJID, accessModel
0639:                        .isAuthorizationRequired(), optionsForm);
0640:            }
0641:
0642:            private void unsubscribeNode(PubSubService service, IQ iq,
0643:                    Element unsubscribeElement) {
0644:                String nodeID = unsubscribeElement.attributeValue("node");
0645:                String subID = unsubscribeElement.attributeValue("subid");
0646:                Node node;
0647:                if (nodeID == null) {
0648:                    if (service.isCollectionNodesSupported()) {
0649:                        // Entity unsubscribes from root collection node
0650:                        node = service.getRootCollectionNode();
0651:                    } else {
0652:                        // Service does not have a root collection node so return a nodeid-required error
0653:                        Element pubsubError = DocumentHelper
0654:                                .createElement(QName
0655:                                        .get("nodeid-required",
0656:                                                "http://jabber.org/protocol/pubsub#errors"));
0657:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0658:                                pubsubError);
0659:                        return;
0660:                    }
0661:                } else {
0662:                    // Look for the specified node
0663:                    node = service.getNode(nodeID);
0664:                    if (node == null) {
0665:                        // Node does not exist. Return item-not-found error
0666:                        sendErrorPacket(iq,
0667:                                PacketError.Condition.item_not_found, null);
0668:                        return;
0669:                    }
0670:                }
0671:                NodeSubscription subscription;
0672:                if (node.isMultipleSubscriptionsEnabled()) {
0673:                    if (subID == null) {
0674:                        // No subid was specified and the node supports multiple subscriptions
0675:                        Element pubsubError = DocumentHelper
0676:                                .createElement(QName
0677:                                        .get("subid-required",
0678:                                                "http://jabber.org/protocol/pubsub#errors"));
0679:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0680:                                pubsubError);
0681:                        return;
0682:                    } else {
0683:                        // Check if the specified subID belongs to an existing node subscription
0684:                        subscription = node.getSubscription(subID);
0685:                        if (subscription == null) {
0686:                            Element pubsubError = DocumentHelper
0687:                                    .createElement(QName
0688:                                            .get("invalid-subid",
0689:                                                    "http://jabber.org/protocol/pubsub#errors"));
0690:                            sendErrorPacket(iq,
0691:                                    PacketError.Condition.not_acceptable,
0692:                                    pubsubError);
0693:                            return;
0694:                        }
0695:                    }
0696:                } else {
0697:                    String jidAttribute = unsubscribeElement
0698:                            .attributeValue("jid");
0699:                    // Check if the specified JID has a subscription with the node
0700:                    if (jidAttribute == null) {
0701:                        // No JID was specified so return an error indicating that jid is required
0702:                        Element pubsubError = DocumentHelper
0703:                                .createElement(QName
0704:                                        .get("jid-required",
0705:                                                "http://jabber.org/protocol/pubsub#errors"));
0706:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0707:                                pubsubError);
0708:                        return;
0709:                    }
0710:                    JID subscriberJID = new JID(jidAttribute);
0711:                    subscription = node.getSubscription(subscriberJID);
0712:                    if (subscription == null) {
0713:                        Element pubsubError = DocumentHelper
0714:                                .createElement(QName
0715:                                        .get("not-subscribed",
0716:                                                "http://jabber.org/protocol/pubsub#errors"));
0717:                        sendErrorPacket(iq,
0718:                                PacketError.Condition.unexpected_request,
0719:                                pubsubError);
0720:                        return;
0721:                    }
0722:                }
0723:                JID from = iq.getFrom();
0724:                // Check that unsubscriptions to the node are enabled
0725:                if (!node.isSubscriptionEnabled()
0726:                        && !service.isServiceAdmin(from)) {
0727:                    // Sender is not a sysadmin and unsubscription is disabled so return an error
0728:                    sendErrorPacket(iq, PacketError.Condition.not_allowed, null);
0729:                    return;
0730:                }
0731:
0732:                // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
0733:                JID owner = new JID(from.toBareJID());
0734:                // A subscription was found so check if the user is allowed to cancel the subscription
0735:                if (!subscription.canModify(from)
0736:                        && !subscription.canModify(owner)) {
0737:                    // Requestor is prohibited from unsubscribing entity
0738:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
0739:                    return;
0740:                }
0741:
0742:                // Cancel subscription
0743:                node.cancelSubscription(subscription);
0744:                // Send reply with success
0745:                router.route(IQ.createResultIQ(iq));
0746:            }
0747:
0748:            private void getSubscriptionConfiguration(PubSubService service,
0749:                    IQ iq, Element childElement, Element optionsElement) {
0750:                String nodeID = optionsElement.attributeValue("node");
0751:                String subID = optionsElement.attributeValue("subid");
0752:                Node node;
0753:                if (nodeID == null) {
0754:                    if (service.isCollectionNodesSupported()) {
0755:                        // Entity requests subscription options of root collection node
0756:                        node = service.getRootCollectionNode();
0757:                    } else {
0758:                        // Service does not have a root collection node so return a nodeid-required error
0759:                        Element pubsubError = DocumentHelper
0760:                                .createElement(QName
0761:                                        .get("nodeid-required",
0762:                                                "http://jabber.org/protocol/pubsub#errors"));
0763:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0764:                                pubsubError);
0765:                        return;
0766:                    }
0767:                } else {
0768:                    // Look for the specified node
0769:                    node = service.getNode(nodeID);
0770:                    if (node == null) {
0771:                        // Node does not exist. Return item-not-found error
0772:                        sendErrorPacket(iq,
0773:                                PacketError.Condition.item_not_found, null);
0774:                        return;
0775:                    }
0776:                }
0777:                NodeSubscription subscription;
0778:                if (node.isMultipleSubscriptionsEnabled()) {
0779:                    if (subID == null) {
0780:                        // No subid was specified and the node supports multiple subscriptions
0781:                        Element pubsubError = DocumentHelper
0782:                                .createElement(QName
0783:                                        .get("subid-required",
0784:                                                "http://jabber.org/protocol/pubsub#errors"));
0785:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0786:                                pubsubError);
0787:                        return;
0788:                    } else {
0789:                        // Check if the specified subID belongs to an existing node subscription
0790:                        subscription = node.getSubscription(subID);
0791:                        if (subscription == null) {
0792:                            Element pubsubError = DocumentHelper
0793:                                    .createElement(QName
0794:                                            .get("invalid-subid",
0795:                                                    "http://jabber.org/protocol/pubsub#errors"));
0796:                            sendErrorPacket(iq,
0797:                                    PacketError.Condition.not_acceptable,
0798:                                    pubsubError);
0799:                            return;
0800:                        }
0801:                    }
0802:                } else {
0803:                    // Check if the specified JID has a subscription with the node
0804:                    String jidAttribute = optionsElement.attributeValue("jid");
0805:                    if (jidAttribute == null) {
0806:                        // No JID was specified so return an error indicating that jid is required
0807:                        Element pubsubError = DocumentHelper
0808:                                .createElement(QName
0809:                                        .get("jid-required",
0810:                                                "http://jabber.org/protocol/pubsub#errors"));
0811:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0812:                                pubsubError);
0813:                        return;
0814:                    }
0815:                    JID subscriberJID = new JID(jidAttribute);
0816:                    subscription = node.getSubscription(subscriberJID);
0817:                    if (subscription == null) {
0818:                        Element pubsubError = DocumentHelper
0819:                                .createElement(QName
0820:                                        .get("not-subscribed",
0821:                                                "http://jabber.org/protocol/pubsub#errors"));
0822:                        sendErrorPacket(iq,
0823:                                PacketError.Condition.unexpected_request,
0824:                                pubsubError);
0825:                        return;
0826:                    }
0827:                }
0828:
0829:                // A subscription was found so check if the user is allowed to get the subscription options
0830:                if (!subscription.canModify(iq.getFrom())) {
0831:                    // Requestor is prohibited from getting the subscription options
0832:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
0833:                    return;
0834:                }
0835:
0836:                // Return data form containing subscription configuration to the subscriber
0837:                IQ reply = IQ.createResultIQ(iq);
0838:                Element replyChildElement = childElement.createCopy();
0839:                reply.setChildElement(replyChildElement);
0840:                replyChildElement.element("options").add(
0841:                        subscription.getConfigurationForm().getElement());
0842:                router.route(reply);
0843:            }
0844:
0845:            private void configureSubscription(PubSubService service, IQ iq,
0846:                    Element optionsElement) {
0847:                String nodeID = optionsElement.attributeValue("node");
0848:                String subID = optionsElement.attributeValue("subid");
0849:                Node node;
0850:                if (nodeID == null) {
0851:                    if (service.isCollectionNodesSupported()) {
0852:                        // Entity submits new subscription options of root collection node
0853:                        node = service.getRootCollectionNode();
0854:                    } else {
0855:                        // Service does not have a root collection node so return a nodeid-required error
0856:                        Element pubsubError = DocumentHelper
0857:                                .createElement(QName
0858:                                        .get("nodeid-required",
0859:                                                "http://jabber.org/protocol/pubsub#errors"));
0860:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0861:                                pubsubError);
0862:                        return;
0863:                    }
0864:                } else {
0865:                    // Look for the specified node
0866:                    node = service.getNode(nodeID);
0867:                    if (node == null) {
0868:                        // Node does not exist. Return item-not-found error
0869:                        sendErrorPacket(iq,
0870:                                PacketError.Condition.item_not_found, null);
0871:                        return;
0872:                    }
0873:                }
0874:                NodeSubscription subscription;
0875:                if (node.isMultipleSubscriptionsEnabled()) {
0876:                    if (subID == null) {
0877:                        // No subid was specified and the node supports multiple subscriptions
0878:                        Element pubsubError = DocumentHelper
0879:                                .createElement(QName
0880:                                        .get("subid-required",
0881:                                                "http://jabber.org/protocol/pubsub#errors"));
0882:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0883:                                pubsubError);
0884:                        return;
0885:                    } else {
0886:                        // Check if the specified subID belongs to an existing node subscription
0887:                        subscription = node.getSubscription(subID);
0888:                        if (subscription == null) {
0889:                            Element pubsubError = DocumentHelper
0890:                                    .createElement(QName
0891:                                            .get("invalid-subid",
0892:                                                    "http://jabber.org/protocol/pubsub#errors"));
0893:                            sendErrorPacket(iq,
0894:                                    PacketError.Condition.not_acceptable,
0895:                                    pubsubError);
0896:                            return;
0897:                        }
0898:                    }
0899:                } else {
0900:                    // Check if the specified JID has a subscription with the node
0901:                    String jidAttribute = optionsElement.attributeValue("jid");
0902:                    if (jidAttribute == null) {
0903:                        // No JID was specified so return an error indicating that jid is required
0904:                        Element pubsubError = DocumentHelper
0905:                                .createElement(QName
0906:                                        .get("jid-required",
0907:                                                "http://jabber.org/protocol/pubsub#errors"));
0908:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
0909:                                pubsubError);
0910:                        return;
0911:                    }
0912:                    JID subscriberJID = new JID(jidAttribute);
0913:                    subscription = node.getSubscription(subscriberJID);
0914:                    if (subscription == null) {
0915:                        Element pubsubError = DocumentHelper
0916:                                .createElement(QName
0917:                                        .get("not-subscribed",
0918:                                                "http://jabber.org/protocol/pubsub#errors"));
0919:                        sendErrorPacket(iq,
0920:                                PacketError.Condition.unexpected_request,
0921:                                pubsubError);
0922:                        return;
0923:                    }
0924:                }
0925:
0926:                // A subscription was found so check if the user is allowed to submits
0927:                // new subscription options
0928:                if (!subscription.canModify(iq.getFrom())) {
0929:                    // Requestor is prohibited from setting new subscription options
0930:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
0931:                    return;
0932:                }
0933:
0934:                Element formElement = optionsElement.element(QName.get("x",
0935:                        "jabber:x:data"));
0936:                if (formElement != null) {
0937:                    // Change the subscription configuration based on the completed form
0938:                    subscription.configure(iq, new DataForm(formElement));
0939:                } else {
0940:                    // No data form was included so return bad request error
0941:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
0942:                }
0943:            }
0944:
0945:            private void getSubscriptions(PubSubService service, IQ iq,
0946:                    Element childElement) {
0947:                // 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
0948:                JID owner = new JID(iq.getFrom().toBareJID());
0949:                // Collect subscriptions of owner for all nodes at the service
0950:                Collection<NodeSubscription> subscriptions = new ArrayList<NodeSubscription>();
0951:                for (Node node : service.getNodes()) {
0952:                    subscriptions.addAll(node.getSubscriptions(owner));
0953:                }
0954:                // Create reply to send
0955:                IQ reply = IQ.createResultIQ(iq);
0956:                Element replyChildElement = childElement.createCopy();
0957:                reply.setChildElement(replyChildElement);
0958:                if (subscriptions.isEmpty()) {
0959:                    // User does not have any affiliation or subscription with the pubsub service
0960:                    reply.setError(PacketError.Condition.item_not_found);
0961:                } else {
0962:                    Element affiliationsElement = replyChildElement
0963:                            .element("subscriptions");
0964:                    // Add information about subscriptions including existing affiliations
0965:                    for (NodeSubscription subscription : subscriptions) {
0966:                        Element subElement = affiliationsElement
0967:                                .addElement("subscription");
0968:                        Node node = subscription.getNode();
0969:                        NodeAffiliate nodeAffiliate = subscription
0970:                                .getAffiliate();
0971:                        // Do not include the node id when node is the root collection node
0972:                        if (!node.isRootCollectionNode()) {
0973:                            subElement.addAttribute("node", node.getNodeID());
0974:                        }
0975:                        subElement.addAttribute("jid", subscription.getJID()
0976:                                .toString());
0977:                        subElement.addAttribute("affiliation", nodeAffiliate
0978:                                .getAffiliation().name());
0979:                        subElement.addAttribute("subscription", subscription
0980:                                .getState().name());
0981:                        if (node.isMultipleSubscriptionsEnabled()) {
0982:                            subElement.addAttribute("subid", subscription
0983:                                    .getID());
0984:                        }
0985:                    }
0986:                }
0987:                // Send reply
0988:                router.route(reply);
0989:            }
0990:
0991:            private void getAffiliations(PubSubService service, IQ iq,
0992:                    Element childElement) {
0993:                // 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
0994:                JID owner = new JID(iq.getFrom().toBareJID());
0995:                // Collect affiliations of owner for all nodes at the service
0996:                Collection<NodeAffiliate> affiliations = new ArrayList<NodeAffiliate>();
0997:                for (Node node : service.getNodes()) {
0998:                    NodeAffiliate nodeAffiliate = node.getAffiliate(owner);
0999:                    if (nodeAffiliate != null) {
1000:                        affiliations.add(nodeAffiliate);
1001:                    }
1002:                }
1003:                // Create reply to send
1004:                IQ reply = IQ.createResultIQ(iq);
1005:                Element replyChildElement = childElement.createCopy();
1006:                reply.setChildElement(replyChildElement);
1007:                if (affiliations.isEmpty()) {
1008:                    // User does not have any affiliation or subscription with the pubsub service
1009:                    reply.setError(PacketError.Condition.item_not_found);
1010:                } else {
1011:                    Element affiliationsElement = replyChildElement
1012:                            .element("affiliations");
1013:                    // Add information about affiliations without subscriptions
1014:                    for (NodeAffiliate affiliate : affiliations) {
1015:                        Element affiliateElement = affiliationsElement
1016:                                .addElement("affiliation");
1017:                        // Do not include the node id when node is the root collection node
1018:                        if (!affiliate.getNode().isRootCollectionNode()) {
1019:                            affiliateElement.addAttribute("node", affiliate
1020:                                    .getNode().getNodeID());
1021:                        }
1022:                        affiliateElement.addAttribute("jid", affiliate.getJID()
1023:                                .toString());
1024:                        affiliateElement.addAttribute("affiliation", affiliate
1025:                                .getAffiliation().name());
1026:                    }
1027:                }
1028:                // Send reply
1029:                router.route(reply);
1030:            }
1031:
1032:            private void getPublishedItems(PubSubService service, IQ iq,
1033:                    Element itemsElement) {
1034:                String nodeID = itemsElement.attributeValue("node");
1035:                String subID = itemsElement.attributeValue("subid");
1036:                Node node;
1037:                if (nodeID == null) {
1038:                    // User must specify a leaf node ID so return a nodeid-required error
1039:                    Element pubsubError = DocumentHelper
1040:                            .createElement(QName.get("nodeid-required",
1041:                                    "http://jabber.org/protocol/pubsub#errors"));
1042:                    sendErrorPacket(iq, PacketError.Condition.bad_request,
1043:                            pubsubError);
1044:                    return;
1045:                } else {
1046:                    // Look for the specified node
1047:                    node = service.getNode(nodeID);
1048:                    if (node == null) {
1049:                        // Node does not exist. Return item-not-found error
1050:                        sendErrorPacket(iq,
1051:                                PacketError.Condition.item_not_found, null);
1052:                        return;
1053:                    }
1054:                }
1055:                if (node.isCollectionNode()) {
1056:                    // Node is a collection node. Return feature-not-implemented error
1057:                    Element pubsubError = DocumentHelper
1058:                            .createElement(QName.get("unsupported",
1059:                                    "http://jabber.org/protocol/pubsub#errors"));
1060:                    pubsubError.addAttribute("feature", "retrieve-items");
1061:                    sendErrorPacket(iq,
1062:                            PacketError.Condition.feature_not_implemented,
1063:                            pubsubError);
1064:                    return;
1065:                }
1066:                // Check if sender and subscriber JIDs match or if a valid "trusted proxy" is being used
1067:                JID subscriberJID = iq.getFrom();
1068:                // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
1069:                JID owner = new JID(subscriberJID.toBareJID());
1070:                // Check if the node's access model allows the subscription to proceed
1071:                AccessModel accessModel = node.getAccessModel();
1072:                if (!accessModel.canAccessItems(node, owner, subscriberJID)) {
1073:                    sendErrorPacket(iq, accessModel.getSubsriptionError(),
1074:                            accessModel.getSubsriptionErrorDetail());
1075:                    return;
1076:                }
1077:                // Check that the requester is not an outcast
1078:                NodeAffiliate affiliate = node.getAffiliate(owner);
1079:                if (affiliate != null
1080:                        && affiliate.getAffiliation() == NodeAffiliate.Affiliation.outcast) {
1081:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1082:                    return;
1083:                }
1084:
1085:                // Get the user's subscription
1086:                NodeSubscription subscription = null;
1087:                if (node.isMultipleSubscriptionsEnabled()
1088:                        && !node.getSubscriptions(owner).isEmpty()) {
1089:                    if (subID == null) {
1090:                        // No subid was specified and the node supports multiple subscriptions
1091:                        Element pubsubError = DocumentHelper
1092:                                .createElement(QName
1093:                                        .get("subid-required",
1094:                                                "http://jabber.org/protocol/pubsub#errors"));
1095:                        sendErrorPacket(iq, PacketError.Condition.bad_request,
1096:                                pubsubError);
1097:                        return;
1098:                    } else {
1099:                        // Check if the specified subID belongs to an existing node subscription
1100:                        subscription = node.getSubscription(subID);
1101:                        if (subscription == null) {
1102:                            Element pubsubError = DocumentHelper
1103:                                    .createElement(QName
1104:                                            .get("invalid-subid",
1105:                                                    "http://jabber.org/protocol/pubsub#errors"));
1106:                            sendErrorPacket(iq,
1107:                                    PacketError.Condition.not_acceptable,
1108:                                    pubsubError);
1109:                            return;
1110:                        }
1111:                    }
1112:                }
1113:
1114:                if (subscription != null && !subscription.isActive()) {
1115:                    Element pubsubError = DocumentHelper
1116:                            .createElement(QName.get("not-subscribed",
1117:                                    "http://jabber.org/protocol/pubsub#errors"));
1118:                    sendErrorPacket(iq, PacketError.Condition.not_authorized,
1119:                            pubsubError);
1120:                    return;
1121:                }
1122:
1123:                LeafNode leafNode = (LeafNode) node;
1124:                // Get list of items to send to the user
1125:                boolean forceToIncludePayload = false;
1126:                List<PublishedItem> items;
1127:                String max_items = itemsElement.attributeValue("max_items");
1128:                int recentItems = 0;
1129:                if (max_items != null) {
1130:                    try {
1131:                        // Parse the recent number of items requested
1132:                        recentItems = Integer.parseInt(max_items);
1133:                    } catch (NumberFormatException e) {
1134:                        // There was an error parsing the number so assume that all items were requested
1135:                        Log.warn("Assuming that all items were requested", e);
1136:                        max_items = null;
1137:                    }
1138:                }
1139:                if (max_items != null) {
1140:                    // Get the N most recent published items
1141:                    items = new ArrayList<PublishedItem>(leafNode
1142:                            .getPublishedItems(recentItems));
1143:                } else {
1144:                    List requestedItems = itemsElement.elements("item");
1145:                    if (requestedItems.isEmpty()) {
1146:                        // Get all the active items that were published to the node
1147:                        items = new ArrayList<PublishedItem>(leafNode
1148:                                .getPublishedItems());
1149:                    } else {
1150:                        items = new ArrayList<PublishedItem>();
1151:                        // Indicate that payload should be included (if exists) no matter
1152:                        // the node configuration
1153:                        forceToIncludePayload = true;
1154:                        // Get the items as requested by the user
1155:                        for (Iterator it = requestedItems.iterator(); it
1156:                                .hasNext();) {
1157:                            Element element = (Element) it.next();
1158:                            String itemID = element.attributeValue("id");
1159:                            PublishedItem item = leafNode
1160:                                    .getPublishedItem(itemID);
1161:                            if (item != null) {
1162:                                items.add(item);
1163:                            }
1164:                        }
1165:                    }
1166:                }
1167:
1168:                if (subscription != null && subscription.getKeyword() != null) {
1169:                    // Filter items that do not match the subscription keyword
1170:                    for (Iterator<PublishedItem> it = items.iterator(); it
1171:                            .hasNext();) {
1172:                        PublishedItem item = it.next();
1173:                        if (!subscription.isKeywordMatched(item)) {
1174:                            // Remove item that does not match keyword
1175:                            it.remove();
1176:                        }
1177:                    }
1178:                }
1179:
1180:                // Send items to the user
1181:                leafNode.sendPublishedItems(iq, items, forceToIncludePayload);
1182:            }
1183:
1184:            private void createNode(PubSubService service, IQ iq,
1185:                    Element childElement, Element createElement) {
1186:                // Get sender of the IQ packet
1187:                JID from = iq.getFrom();
1188:                // Verify that sender has permissions to create nodes
1189:                if (!service.canCreateNode(from)
1190:                        || !UserManager.getInstance().isRegisteredUser(from)) {
1191:                    // The user is not allowed to create nodes so return an error
1192:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1193:                    return;
1194:                }
1195:                DataForm completedForm = null;
1196:                CollectionNode parentNode = null;
1197:                String nodeID = createElement.attributeValue("node");
1198:                String newNodeID = nodeID;
1199:                if (nodeID == null) {
1200:                    // User requested an instant node
1201:                    if (!service.isInstantNodeSupported()) {
1202:                        // Instant nodes creation is not allowed so return an error
1203:                        Element pubsubError = DocumentHelper
1204:                                .createElement(QName
1205:                                        .get("nodeid-required",
1206:                                                "http://jabber.org/protocol/pubsub#errors"));
1207:                        sendErrorPacket(iq,
1208:                                PacketError.Condition.not_acceptable,
1209:                                pubsubError);
1210:                        return;
1211:                    }
1212:                    do {
1213:                        // Create a new nodeID and make sure that the random generated string does not
1214:                        // match an existing node. Probability to match an existing node are very very low
1215:                        // but they exist :)
1216:                        newNodeID = StringUtils.randomString(15);
1217:                    } while (service.getNode(newNodeID) != null);
1218:                }
1219:                boolean collectionType = false;
1220:                // Check if user requested to configure the node (using a data form)
1221:                Element configureElement = childElement.element("configure");
1222:                if (configureElement != null) {
1223:                    // Get the data form that contains the parent nodeID
1224:                    completedForm = getSentConfigurationForm(configureElement);
1225:                    if (completedForm != null) {
1226:                        // Calculate newNodeID when new node is affiliated with a Collection
1227:                        FormField field = completedForm
1228:                                .getField("pubsub#collection");
1229:                        if (field != null) {
1230:                            List<String> values = field.getValues();
1231:                            if (!values.isEmpty()) {
1232:                                String parentNodeID = values.get(0);
1233:                                Node tempNode = service.getNode(parentNodeID);
1234:                                if (tempNode == null) {
1235:                                    // Requested parent node was not found so return an error
1236:                                    sendErrorPacket(
1237:                                            iq,
1238:                                            PacketError.Condition.item_not_found,
1239:                                            null);
1240:                                    return;
1241:                                } else if (!tempNode.isCollectionNode()) {
1242:                                    // Requested parent node is not a collection node so return an error
1243:                                    sendErrorPacket(
1244:                                            iq,
1245:                                            PacketError.Condition.not_acceptable,
1246:                                            null);
1247:                                    return;
1248:                                }
1249:                                parentNode = (CollectionNode) tempNode;
1250:                            }
1251:                        }
1252:                        field = completedForm.getField("pubsub#node_type");
1253:                        if (field != null) {
1254:                            // Check if user requested to create a new collection node
1255:                            List<String> values = field.getValues();
1256:                            if (!values.isEmpty()) {
1257:                                collectionType = "collection".equals(values
1258:                                        .get(0));
1259:                            }
1260:                        }
1261:                    }
1262:                }
1263:                // If no parent was defined then use the root collection node
1264:                if (parentNode == null && service.isCollectionNodesSupported()) {
1265:                    parentNode = service.getRootCollectionNode();
1266:                }
1267:                // Check that the requested nodeID does not exist
1268:                Node existingNode = service.getNode(newNodeID);
1269:                if (existingNode != null) {
1270:                    // There is a conflict since a node with the same ID already exists
1271:                    sendErrorPacket(iq, PacketError.Condition.conflict, null);
1272:                    return;
1273:                }
1274:
1275:                if (collectionType && !service.isCollectionNodesSupported()) {
1276:                    // Cannot create a collection node since the service doesn't support it
1277:                    Element pubsubError = DocumentHelper
1278:                            .createElement(QName.get("unsupported",
1279:                                    "http://jabber.org/protocol/pubsub#errors"));
1280:                    pubsubError.addAttribute("feature", "collections");
1281:                    sendErrorPacket(iq,
1282:                            PacketError.Condition.feature_not_implemented,
1283:                            pubsubError);
1284:                    return;
1285:                }
1286:
1287:                if (parentNode != null && !collectionType) {
1288:                    // Check if requester is allowed to add a new leaf child node to the parent node
1289:                    if (!parentNode.isAssociationAllowed(from)) {
1290:                        // User is not allowed to add child leaf node to parent node. Return an error.
1291:                        sendErrorPacket(iq, PacketError.Condition.forbidden,
1292:                                null);
1293:                        return;
1294:                    }
1295:                    // Check if number of child leaf nodes has not been exceeded
1296:                    if (parentNode.isMaxLeafNodeReached()) {
1297:                        // Max number of child leaf nodes has been reached. Return an error.
1298:                        Element pubsubError = DocumentHelper
1299:                                .createElement(QName
1300:                                        .get("max-nodes-exceeded",
1301:                                                "http://jabber.org/protocol/pubsub#errors"));
1302:                        sendErrorPacket(iq, PacketError.Condition.conflict,
1303:                                pubsubError);
1304:                        return;
1305:                    }
1306:                }
1307:
1308:                // Create and configure the node
1309:                boolean conflict = false;
1310:                Node newNode = null;
1311:                try {
1312:                    // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
1313:                    JID owner = new JID(from.toBareJID());
1314:                    synchronized (newNodeID.intern()) {
1315:                        if (service.getNode(newNodeID) == null) {
1316:                            // Create the node
1317:                            if (collectionType) {
1318:                                newNode = new CollectionNode(service,
1319:                                        parentNode, newNodeID, from);
1320:                            } else {
1321:                                newNode = new LeafNode(service, parentNode,
1322:                                        newNodeID, from);
1323:                            }
1324:                            // Add the creator as the node owner
1325:                            newNode.addOwner(owner);
1326:                            // Configure and save the node to the backend store
1327:                            if (completedForm != null) {
1328:                                newNode.configure(completedForm);
1329:                            } else {
1330:                                newNode.saveToDB();
1331:                            }
1332:                        } else {
1333:                            conflict = true;
1334:                        }
1335:                    }
1336:                    if (conflict) {
1337:                        // There is a conflict since a node with the same ID already exists
1338:                        sendErrorPacket(iq, PacketError.Condition.conflict,
1339:                                null);
1340:                    } else {
1341:                        // Return success to the node owner
1342:                        IQ reply = IQ.createResultIQ(iq);
1343:                        // Include new nodeID if it has changed from the original nodeID
1344:                        if (!newNode.getNodeID().equals(nodeID)) {
1345:                            Element elem = reply.setChildElement("pubsub",
1346:                                    "http://jabber.org/protocol/pubsub");
1347:                            elem.addElement("create").addAttribute("node",
1348:                                    newNode.getNodeID());
1349:                        }
1350:                        router.route(reply);
1351:                    }
1352:                } catch (NotAcceptableException e) {
1353:                    // Node should have at least one owner. Return not-acceptable error.
1354:                    sendErrorPacket(iq, PacketError.Condition.not_acceptable,
1355:                            null);
1356:                }
1357:            }
1358:
1359:            private void getNodeConfiguration(PubSubService service, IQ iq,
1360:                    Element childElement, String nodeID) {
1361:                Node node = service.getNode(nodeID);
1362:                if (node == null) {
1363:                    // Node does not exist. Return item-not-found error
1364:                    sendErrorPacket(iq, PacketError.Condition.item_not_found,
1365:                            null);
1366:                    return;
1367:                }
1368:                if (!node.isAdmin(iq.getFrom())) {
1369:                    // Requesting entity is prohibited from configuring this node. Return forbidden error
1370:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1371:                    return;
1372:                }
1373:
1374:                // Return data form containing node configuration to the owner
1375:                IQ reply = IQ.createResultIQ(iq);
1376:                Element replyChildElement = childElement.createCopy();
1377:                reply.setChildElement(replyChildElement);
1378:                replyChildElement.element("configure").add(
1379:                        node.getConfigurationForm().getElement());
1380:                router.route(reply);
1381:            }
1382:
1383:            private void getDefaultNodeConfiguration(PubSubService service,
1384:                    IQ iq, Element childElement, Element defaultElement) {
1385:                String type = defaultElement.attributeValue("type");
1386:                type = type == null ? "leaf" : type;
1387:
1388:                boolean isLeafType = "leaf".equals(type);
1389:                DefaultNodeConfiguration config = service
1390:                        .getDefaultNodeConfiguration(isLeafType);
1391:                if (config == null) {
1392:                    // Service does not support the requested node type so return an error
1393:                    Element pubsubError = DocumentHelper
1394:                            .createElement(QName.get("unsupported",
1395:                                    "http://jabber.org/protocol/pubsub#errors"));
1396:                    pubsubError.addAttribute("feature", isLeafType ? "leaf"
1397:                            : "collections");
1398:                    sendErrorPacket(iq,
1399:                            PacketError.Condition.feature_not_implemented,
1400:                            pubsubError);
1401:                    return;
1402:                }
1403:
1404:                // Return data form containing default node configuration
1405:                IQ reply = IQ.createResultIQ(iq);
1406:                Element replyChildElement = childElement.createCopy();
1407:                reply.setChildElement(replyChildElement);
1408:                replyChildElement.element("default").add(
1409:                        config.getConfigurationForm().getElement());
1410:                router.route(reply);
1411:            }
1412:
1413:            private void configureNode(PubSubService service, IQ iq,
1414:                    Element configureElement, String nodeID) {
1415:                Node node = service.getNode(nodeID);
1416:                if (node == null) {
1417:                    // Node does not exist. Return item-not-found error
1418:                    sendErrorPacket(iq, PacketError.Condition.item_not_found,
1419:                            null);
1420:                    return;
1421:                }
1422:                if (!node.isAdmin(iq.getFrom())) {
1423:                    // Requesting entity is not allowed to get node configuration. Return forbidden error
1424:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1425:                    return;
1426:                }
1427:
1428:                // Get the data form that contains the parent nodeID
1429:                DataForm completedForm = getSentConfigurationForm(configureElement);
1430:                if (completedForm != null) {
1431:                    try {
1432:                        // Update node configuration with the provided data form
1433:                        // (and update the backend store)
1434:                        node.configure(completedForm);
1435:                        // Return that node configuration was successful
1436:                        router.route(IQ.createResultIQ(iq));
1437:                    } catch (NotAcceptableException e) {
1438:                        // Node should have at least one owner. Return not-acceptable error.
1439:                        sendErrorPacket(iq,
1440:                                PacketError.Condition.not_acceptable, null);
1441:                    }
1442:                } else {
1443:                    // No data form was included so return bad-request error
1444:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
1445:                }
1446:            }
1447:
1448:            private void deleteNode(PubSubService service, IQ iq,
1449:                    Element deleteElement) {
1450:                String nodeID = deleteElement.attributeValue("node");
1451:                if (nodeID == null) {
1452:                    // NodeID was not provided. Return bad-request error
1453:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
1454:                    return;
1455:                }
1456:                Node node = service.getNode(nodeID);
1457:                if (node == null) {
1458:                    // Node does not exist. Return item-not-found error
1459:                    sendErrorPacket(iq, PacketError.Condition.item_not_found,
1460:                            null);
1461:                    return;
1462:                }
1463:                if (!node.isAdmin(iq.getFrom())) {
1464:                    // Requesting entity is prohibited from deleting this node. Return forbidden error
1465:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1466:                    return;
1467:                }
1468:                if (node.isRootCollectionNode()) {
1469:                    // Root collection node cannot be deleted. Return not-allowed error
1470:                    sendErrorPacket(iq, PacketError.Condition.not_allowed, null);
1471:                    return;
1472:                }
1473:
1474:                // Delete the node
1475:                if (node.delete()) {
1476:                    // Return that node was deleted successfully
1477:                    router.route(IQ.createResultIQ(iq));
1478:                } else {
1479:                    // Some error occured while trying to delete the node
1480:                    sendErrorPacket(iq,
1481:                            PacketError.Condition.internal_server_error, null);
1482:                }
1483:            }
1484:
1485:            private void purgeNode(PubSubService service, IQ iq,
1486:                    Element purgeElement) {
1487:                String nodeID = purgeElement.attributeValue("node");
1488:                if (nodeID == null) {
1489:                    // NodeID was not provided. Return bad-request error
1490:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
1491:                    return;
1492:                }
1493:                Node node = service.getNode(nodeID);
1494:                if (node == null) {
1495:                    // Node does not exist. Return item-not-found error
1496:                    sendErrorPacket(iq, PacketError.Condition.item_not_found,
1497:                            null);
1498:                    return;
1499:                }
1500:                if (!node.isAdmin(iq.getFrom())) {
1501:                    // Requesting entity is prohibited from configuring this node. Return forbidden error
1502:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1503:                    return;
1504:                }
1505:                if (!((LeafNode) node).isPersistPublishedItems()) {
1506:                    // Node does not persist items. Return feature-not-implemented error
1507:                    Element pubsubError = DocumentHelper
1508:                            .createElement(QName.get("unsupported",
1509:                                    "http://jabber.org/protocol/pubsub#errors"));
1510:                    pubsubError.addAttribute("feature", "persistent-items");
1511:                    sendErrorPacket(iq,
1512:                            PacketError.Condition.feature_not_implemented,
1513:                            pubsubError);
1514:                    return;
1515:                }
1516:                if (node.isCollectionNode()) {
1517:                    // Node is a collection node. Return feature-not-implemented error
1518:                    Element pubsubError = DocumentHelper
1519:                            .createElement(QName.get("unsupported",
1520:                                    "http://jabber.org/protocol/pubsub#errors"));
1521:                    pubsubError.addAttribute("feature", "purge-nodes");
1522:                    sendErrorPacket(iq,
1523:                            PacketError.Condition.feature_not_implemented,
1524:                            pubsubError);
1525:                    return;
1526:                }
1527:
1528:                // Purge the node
1529:                ((LeafNode) node).purge();
1530:                // Return that node purged successfully
1531:                router.route(IQ.createResultIQ(iq));
1532:            }
1533:
1534:            private void getNodeSubscriptions(PubSubService service, IQ iq,
1535:                    Element affiliationsElement) {
1536:                String nodeID = affiliationsElement.attributeValue("node");
1537:                if (nodeID == null) {
1538:                    // NodeID was not provided. Return bad-request error.
1539:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
1540:                    return;
1541:                }
1542:                Node node = service.getNode(nodeID);
1543:                if (node == null) {
1544:                    // Node does not exist. Return item-not-found error.
1545:                    sendErrorPacket(iq, PacketError.Condition.item_not_found,
1546:                            null);
1547:                    return;
1548:                }
1549:                if (!node.isAdmin(iq.getFrom())) {
1550:                    // Requesting entity is prohibited from getting affiliates list. Return forbidden error.
1551:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1552:                    return;
1553:                }
1554:
1555:                // Ask the node to send the list of subscriptions to the owner
1556:                node.sendSubscriptions(iq);
1557:            }
1558:
1559:            private void modifyNodeSubscriptions(PubSubService service, IQ iq,
1560:                    Element entitiesElement) {
1561:                String nodeID = entitiesElement.attributeValue("node");
1562:                if (nodeID == null) {
1563:                    // NodeID was not provided. Return bad-request error.
1564:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
1565:                    return;
1566:                }
1567:                Node node = service.getNode(nodeID);
1568:                if (node == null) {
1569:                    // Node does not exist. Return item-not-found error.
1570:                    sendErrorPacket(iq, PacketError.Condition.item_not_found,
1571:                            null);
1572:                    return;
1573:                }
1574:                if (!node.isAdmin(iq.getFrom())) {
1575:                    // Requesting entity is prohibited from getting affiliates list. Return forbidden error.
1576:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1577:                    return;
1578:                }
1579:
1580:                IQ reply = IQ.createResultIQ(iq);
1581:
1582:                // Process modifications or creations of affiliations and subscriptions.
1583:                for (Iterator it = entitiesElement
1584:                        .elementIterator("subscription"); it.hasNext();) {
1585:                    Element entity = (Element) it.next();
1586:                    JID subscriber = new JID(entity.attributeValue("jid"));
1587:                    // TODO Assumed that the owner of the subscription is the bare JID of the subscription JID. Waiting StPeter answer for explicit field.
1588:                    JID owner = new JID(subscriber.toBareJID());
1589:                    String subStatus = entity.attributeValue("subscription");
1590:                    String subID = entity.attributeValue("subid");
1591:                    // Process subscriptions changes
1592:                    // Get current subscription (if any)
1593:                    NodeSubscription subscription = null;
1594:                    if (node.isMultipleSubscriptionsEnabled()) {
1595:                        if (subID != null) {
1596:                            subscription = node.getSubscription(subID);
1597:                        }
1598:                    } else {
1599:                        subscription = node.getSubscription(subscriber);
1600:                    }
1601:                    if ("none".equals(subStatus) && subscription != null) {
1602:                        // Owner is cancelling an existing subscription
1603:                        node.cancelSubscription(subscription);
1604:                    } else if ("subscribed".equals(subStatus)) {
1605:                        if (subscription != null) {
1606:                            // Owner is approving a subscription (i.e. making active)
1607:                            node.approveSubscription(subscription, true);
1608:                        } else {
1609:                            // Owner is creating a subscription for an entity to the node
1610:                            node.createSubscription(null, owner, subscriber,
1611:                                    false, null);
1612:                        }
1613:                    }
1614:                }
1615:
1616:                // Send reply
1617:                router.route(reply);
1618:            }
1619:
1620:            private void getNodeAffiliations(PubSubService service, IQ iq,
1621:                    Element affiliationsElement) {
1622:                String nodeID = affiliationsElement.attributeValue("node");
1623:                if (nodeID == null) {
1624:                    // NodeID was not provided. Return bad-request error.
1625:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
1626:                    return;
1627:                }
1628:                Node node = service.getNode(nodeID);
1629:                if (node == null) {
1630:                    // Node does not exist. Return item-not-found error.
1631:                    sendErrorPacket(iq, PacketError.Condition.item_not_found,
1632:                            null);
1633:                    return;
1634:                }
1635:                if (!node.isAdmin(iq.getFrom())) {
1636:                    // Requesting entity is prohibited from getting affiliates list. Return forbidden error.
1637:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1638:                    return;
1639:                }
1640:
1641:                // Ask the node to send the list of affiliations to the owner
1642:                node.sendAffiliations(iq);
1643:            }
1644:
1645:            private void modifyNodeAffiliations(PubSubService service, IQ iq,
1646:                    Element entitiesElement) {
1647:                String nodeID = entitiesElement.attributeValue("node");
1648:                if (nodeID == null) {
1649:                    // NodeID was not provided. Return bad-request error.
1650:                    sendErrorPacket(iq, PacketError.Condition.bad_request, null);
1651:                    return;
1652:                }
1653:                Node node = service.getNode(nodeID);
1654:                if (node == null) {
1655:                    // Node does not exist. Return item-not-found error.
1656:                    sendErrorPacket(iq, PacketError.Condition.item_not_found,
1657:                            null);
1658:                    return;
1659:                }
1660:                if (!node.isAdmin(iq.getFrom())) {
1661:                    // Requesting entity is prohibited from getting affiliates list. Return forbidden error.
1662:                    sendErrorPacket(iq, PacketError.Condition.forbidden, null);
1663:                    return;
1664:                }
1665:
1666:                IQ reply = IQ.createResultIQ(iq);
1667:                Collection<JID> invalidAffiliates = new ArrayList<JID>();
1668:
1669:                // Process modifications or creations of affiliations
1670:                for (Iterator it = entitiesElement
1671:                        .elementIterator("affiliation"); it.hasNext();) {
1672:                    Element affiliation = (Element) it.next();
1673:                    JID owner = new JID(affiliation.attributeValue("jid"));
1674:                    String newAffiliation = affiliation
1675:                            .attributeValue("affiliation");
1676:                    // Get current affiliation of this user (if any)
1677:                    NodeAffiliate affiliate = node.getAffiliate(owner);
1678:
1679:                    // Check that we are not removing the only owner of the node
1680:                    if (affiliate != null
1681:                            && !affiliate.getAffiliation().name().equals(
1682:                                    newAffiliation)) {
1683:                        // Trying to modify an existing affiliation
1684:                        if (affiliate.getAffiliation() == NodeAffiliate.Affiliation.owner
1685:                                && node.getOwners().size() == 1) {
1686:                            // Trying to remove the unique owner of the node. Include in error answer.
1687:                            invalidAffiliates.add(owner);
1688:                            continue;
1689:                        }
1690:                    }
1691:
1692:                    // Owner is setting affiliations for new entities or modifying
1693:                    // existing affiliations
1694:                    if ("owner".equals(newAffiliation)) {
1695:                        node.addOwner(owner);
1696:                    } else if ("publisher".equals(newAffiliation)) {
1697:                        node.addPublisher(owner);
1698:                    } else if ("none".equals(newAffiliation)) {
1699:                        node.addNoneAffiliation(owner);
1700:                    } else {
1701:                        node.addOutcast(owner);
1702:                    }
1703:                }
1704:
1705:                // Process invalid entities that tried to remove node owners. Send original affiliation
1706:                // of the invalid entities.
1707:                if (!invalidAffiliates.isEmpty()) {
1708:                    reply.setError(PacketError.Condition.not_acceptable);
1709:                    Element child = reply.setChildElement("pubsub",
1710:                            "http://jabber.org/protocol/pubsub#owner");
1711:                    Element entities = child.addElement("affiliations");
1712:                    if (!node.isRootCollectionNode()) {
1713:                        entities.addAttribute("node", node.getNodeID());
1714:                    }
1715:                    for (JID affiliateJID : invalidAffiliates) {
1716:                        NodeAffiliate affiliate = node
1717:                                .getAffiliate(affiliateJID);
1718:                        Element entity = entities.addElement("affiliation");
1719:                        entity.addAttribute("jid", affiliate.getJID()
1720:                                .toString());
1721:                        entity.addAttribute("affiliation", affiliate
1722:                                .getAffiliation().name());
1723:                    }
1724:                }
1725:                // Send reply
1726:                router.route(reply);
1727:            }
1728:
1729:            /**
1730:             * Terminates the subscription of the specified entity to all nodes hosted at the service.
1731:             * The affiliation with the node will be removed if the entity was not a node owner or
1732:             * publisher.
1733:             *
1734:             * @param service the PubSub service this action is to be performed for.
1735:             * @param user the entity that no longer exists.
1736:             */
1737:            private void cancelAllSubscriptions(PubSubService service, JID user) {
1738:                for (Node node : service.getNodes()) {
1739:                    NodeAffiliate affiliate = node.getAffiliate(user);
1740:                    if (affiliate == null) {
1741:                        continue;
1742:                    }
1743:                    for (NodeSubscription subscription : affiliate
1744:                            .getSubscriptions()) {
1745:                        // Cancel subscription
1746:                        node.cancelSubscription(subscription);
1747:                    }
1748:                }
1749:            }
1750:
1751:            private void processAuthorizationAnswer(PubSubService service,
1752:                    DataForm authForm, Message message) {
1753:                String nodeID = authForm.getField("pubsub#node").getValues()
1754:                        .get(0);
1755:                String subID = authForm.getField("pubsub#subid").getValues()
1756:                        .get(0);
1757:                String allow = authForm.getField("pubsub#allow").getValues()
1758:                        .get(0);
1759:                boolean approved;
1760:                if ("1".equals(allow) || "true".equals(allow)) {
1761:                    approved = true;
1762:                } else if ("0".equals(allow) || "false".equals(allow)) {
1763:                    approved = false;
1764:                } else {
1765:                    // Unknown allow value. Ignore completed form
1766:                    Log
1767:                            .warn("Invalid allow value in completed authorization form: "
1768:                                    + message.toXML());
1769:                    return;
1770:                }
1771:                // Approve or cancel the pending subscription to the node
1772:                Node node = service.getNode(nodeID);
1773:                if (node != null) {
1774:                    NodeSubscription subscription = node.getSubscription(subID);
1775:                    if (subscription != null) {
1776:                        node.approveSubscription(subscription, approved);
1777:                    }
1778:                }
1779:            }
1780:
1781:            /**
1782:             * Generate a conflict packet to indicate that the nickname being requested/used is already in
1783:             * use by another user.
1784:             *
1785:             * @param packet the packet to be bounced.
1786:             */
1787:            void sendErrorPacket(IQ packet, PacketError.Condition error,
1788:                    Element pubsubError) {
1789:                IQ reply = IQ.createResultIQ(packet);
1790:                reply.setChildElement(packet.getChildElement().createCopy());
1791:                reply.setError(error);
1792:                if (pubsubError != null) {
1793:                    // Add specific pubsub error if available
1794:                    reply.getError().getElement().add(pubsubError);
1795:                }
1796:                router.route(reply);
1797:            }
1798:
1799:            /**
1800:             * Returns the data form included in the configure element sent by the node owner or
1801:             * <tt>null</tt> if none was included or access model was defined. If the
1802:             * owner just wants to set the access model to use for the node and optionally set the
1803:             * list of roster groups (i.e. contacts present in the node owner roster in the
1804:             * specified groups are allowed to access the node) allowed to access the node then
1805:             * instead of including a data form the owner can just specify the "access" attribute
1806:             * of the configure element and optionally include a list of group elements. In this case,
1807:             * the method will create a data form including the specified data. This is a nice way
1808:             * to accept both ways to configure a node but always returning a data form.
1809:             *
1810:             * @param configureElement the configure element sent by the owner.
1811:             * @return the data form included in the configure element sent by the node owner or
1812:             *         <tt>null</tt> if none was included or access model was defined.
1813:             */
1814:            private DataForm getSentConfigurationForm(Element configureElement) {
1815:                DataForm completedForm = null;
1816:                FormField formField;
1817:                Element formElement = configureElement.element(QName.get("x",
1818:                        "jabber:x:data"));
1819:                if (formElement != null) {
1820:                    completedForm = new DataForm(formElement);
1821:                }
1822:                String accessModel = configureElement.attributeValue("access");
1823:                if (accessModel != null) {
1824:                    if (completedForm == null) {
1825:                        // Create a form (i.e. simulate that the user sent a form with roster groups)
1826:                        completedForm = new DataForm(DataForm.Type.submit);
1827:                        // Add the hidden field indicating that this is a node config form
1828:                        formField = completedForm.addField();
1829:                        formField.setVariable("FORM_TYPE");
1830:                        formField.setType(FormField.Type.hidden);
1831:                        formField
1832:                                .addValue("http://jabber.org/protocol/pubsub#node_config");
1833:                    }
1834:                    if (completedForm.getField("pubsub#access_model") == null) {
1835:                        // Add the field that will specify the access model of the node
1836:                        formField = completedForm.addField();
1837:                        formField.setVariable("pubsub#access_model");
1838:                        formField.addValue(accessModel);
1839:                    } else {
1840:                        Log
1841:                                .debug("PubSubEngine: Owner sent access model in data form and as attribute: "
1842:                                        + configureElement.asXML());
1843:                    }
1844:                    // Check if a list of groups was specified
1845:                    List groups = configureElement.elements("group");
1846:                    if (!groups.isEmpty()) {
1847:                        // Add the field that will contain the specified groups
1848:                        formField = completedForm.addField();
1849:                        formField.setVariable("pubsub#roster_groups_allowed");
1850:                        // Add each group as a value of the groups field
1851:                        for (Iterator it = groups.iterator(); it.hasNext();) {
1852:                            formField.addValue(((Element) it.next())
1853:                                    .getTextTrim());
1854:                        }
1855:                    }
1856:                }
1857:                return completedForm;
1858:            }
1859:
1860:            public void start(final PubSubService service) {
1861:                // Probe presences of users that this service has subscribed to (once the server
1862:                // has started)
1863:
1864:                if (XMPPServer.getInstance().isStarted()) {
1865:                    probePresences(service);
1866:                } else {
1867:                    XMPPServer.getInstance().addServerListener(
1868:                            new XMPPServerListener() {
1869:                                public void serverStarted() {
1870:                                    probePresences(service);
1871:                                }
1872:
1873:                                public void serverStopping() {
1874:                                }
1875:                            });
1876:                }
1877:            }
1878:
1879:            private void probePresences(final PubSubService service) {
1880:                Set<JID> affiliates = new HashSet<JID>();
1881:                for (Node node : service.getNodes()) {
1882:                    affiliates.addAll(node.getPresenceBasedSubscribers());
1883:                }
1884:                for (JID jid : affiliates) {
1885:                    // Send probe presence
1886:                    Presence subscription = new Presence(Presence.Type.probe);
1887:                    subscription.setTo(jid);
1888:                    subscription.setFrom(service.getAddress());
1889:                    service.send(subscription);
1890:                }
1891:            }
1892:
1893:            public void shutdown(PubSubService service) {
1894:                // Stop the maintenance processes
1895:                service.getTimer().cancel();
1896:                // Delete from the database items contained in the itemsToDelete queue
1897:                PublishedItem entry;
1898:                while (!service.getItemsToDelete().isEmpty()) {
1899:                    entry = service.getItemsToDelete().poll();
1900:                    if (entry != null) {
1901:                        PubSubPersistenceManager.removePublishedItem(service,
1902:                                entry);
1903:                    }
1904:                }
1905:                // Save to the database items contained in the itemsToAdd queue
1906:                while (!service.getItemsToAdd().isEmpty()) {
1907:                    entry = service.getItemsToAdd().poll();
1908:                    if (entry != null) {
1909:                        PubSubPersistenceManager.createPublishedItem(service,
1910:                                entry);
1911:                    }
1912:                }
1913:                // Stop executing ad-hoc commands
1914:                service.getManager().stop();
1915:            }
1916:
1917:            /*******************************************************************************
1918:             * Methods related to presence subscriptions to subscribers' presence.
1919:             ******************************************************************************/
1920:
1921:            /**
1922:             * Returns the show values of the last know presence of all connected resources of the
1923:             * specified subscriber. When the subscriber JID is a bare JID then the answered collection
1924:             * will have many entries one for each connected resource. Moreover, if the user
1925:             * is offline then an empty collectin is returned. Available show status is represented
1926:             * by a <tt>online</tt> value. The rest of the possible show values as defined in RFC 3921.
1927:             *
1928:             * @param service the PubSub service this action is to be performed for.
1929:             * @param subscriber the JID of the subscriber. This is not the JID of the affiliate.
1930:             * @return an empty collection when offline. Otherwise, a collection with the show value
1931:             *         of each connected resource.
1932:             */
1933:            public static Collection<String> getShowPresences(
1934:                    PubSubService service, JID subscriber) {
1935:                Map<String, String> fullPresences = service.getBarePresences()
1936:                        .get(subscriber.toBareJID());
1937:                if (fullPresences == null) {
1938:                    // User is offline so return empty list
1939:                    return Collections.emptyList();
1940:                }
1941:                if (subscriber.getResource() == null) {
1942:                    // Subscriber used bared JID so return show value of all connected resources
1943:                    return fullPresences.values();
1944:                } else {
1945:                    // Look for the show value using the full JID
1946:                    String show = fullPresences.get(subscriber.toString());
1947:                    if (show == null) {
1948:                        // User at the specified resource is offline so return empty list
1949:                        return Collections.emptyList();
1950:                    }
1951:                    // User is connected at specified resource so answer list with presence show value
1952:                    return Arrays.asList(show);
1953:                }
1954:            }
1955:
1956:            /**
1957:             * Requests the pubsub service to subscribe to the presence of the user. If the service
1958:             * has already subscribed to the user's presence then do nothing.
1959:             *
1960:             * @param service the PubSub service this action is to be performed for.
1961:             * @param node the node that originated the subscription request.
1962:             * @param user the JID of the affiliate to subscribe to his presence.
1963:             */
1964:            public static void presenceSubscriptionNotRequired(
1965:                    PubSubService service, Node node, JID user) {
1966:                // Check that no node is requiring to be subscribed to this user
1967:                for (Node hostedNode : service.getNodes()) {
1968:                    if (hostedNode.isPresenceBasedDelivery(user)) {
1969:                        // Do not unsubscribe since presence subscription is still required
1970:                        return;
1971:                    }
1972:                }
1973:                // Unscribe from the user presence
1974:                Presence subscription = new Presence(Presence.Type.unsubscribe);
1975:                subscription.setTo(user);
1976:                subscription.setFrom(service.getAddress());
1977:                service.send(subscription);
1978:            }
1979:
1980:            /**
1981:             * Requests the pubsub service to unsubscribe from the presence of the user. If the service
1982:             * was not subscribed to the user's presence or any node still requires to be subscribed to
1983:             * the user presence then do nothing.
1984:             *
1985:             * @param service the PubSub service this action is to be performed for.
1986:             * @param node the node that originated the unsubscription request.
1987:             * @param user the JID of the affiliate to unsubscribe from his presence.
1988:             */
1989:            public static void presenceSubscriptionRequired(
1990:                    PubSubService service, Node node, JID user) {
1991:                Map<String, String> fullPresences = service.getBarePresences()
1992:                        .get(user.toString());
1993:                if (fullPresences == null || fullPresences.isEmpty()) {
1994:                    Presence subscription = new Presence(
1995:                            Presence.Type.subscribe);
1996:                    subscription.setTo(user);
1997:                    subscription.setFrom(service.getAddress());
1998:                    service.send(subscription);
1999:                    // Sending subscription requests based on received presences may generate
2000:                    // that a sunscription request is sent to an offline user (since offline
2001:                    // presences are not stored in the service's "barePresences"). However, this
2002:                    // not optimal algorithm shouldn't bother the user since the user's server
2003:                    // should reply when already subscribed to the user's presence instead of
2004:                    // asking the user to accept the subscription request.
2005:                }
2006:            }
2007:
2008:            /*******************************************************************************
2009:             * Methods related to PubSub maintenance tasks. Such as
2010:             * saving or deleting published items.
2011:             ******************************************************************************/
2012:
2013:            /**
2014:             * Schedules the maintenance task for repeated <i>fixed-delay execution</i>,
2015:             * beginning after the specified delay.  Subsequent executions take place
2016:             * at approximately regular intervals separated by the specified period.
2017:             *
2018:             * @param service the PubSub service this action is to be performed for.
2019:             * @param timeout the new frequency of the maintenance task.
2020:             */
2021:            void setPublishedItemTaskTimeout(PubSubService service, int timeout) {
2022:                int items_task_timeout = service.getItemsTaskTimeout();
2023:                if (items_task_timeout == timeout) {
2024:                    return;
2025:                }
2026:                // Cancel the existing task because the timeout has changed
2027:                PublishedItemTask publishedItemTask = service
2028:                        .getPublishedItemTask();
2029:                if (publishedItemTask != null) {
2030:                    publishedItemTask.cancel();
2031:                }
2032:                service.setItemsTaskTimeout(timeout);
2033:                // Create a new task and schedule it with the new timeout
2034:                service.setPublishedItemTask(new PublishedItemTask(service));
2035:                service.getTimer().schedule(publishedItemTask,
2036:                        items_task_timeout, items_task_timeout);
2037:            }
2038:
2039:            /**
2040:             * Adds the item to the queue of items to remove from the database. The queue is going
2041:             * to be processed by another thread.
2042:             *
2043:             * @param service the PubSub service this action is to be performed for.
2044:             * @param removedItem the item to remove from the database.
2045:             */
2046:            public static void queueItemToRemove(PubSubService service,
2047:                    PublishedItem removedItem) {
2048:                // Remove the removed item from the queue of items to add to the database
2049:                if (!service.getItemsToAdd().remove(removedItem)) {
2050:                    // The item is already present in the database so add the removed item
2051:                    // to the queue of items to delete from the database
2052:                    service.getItemsToDelete().add(removedItem);
2053:                }
2054:            }
2055:
2056:            /**
2057:             * Adds the item to the queue of items to add to the database. The queue is going
2058:             * to be processed by another thread.
2059:             *
2060:             * @param service the PubSub service this action is to be performed for.
2061:             * @param newItem the item to add to the database.
2062:             */
2063:            public static void queueItemToAdd(PubSubService service,
2064:                    PublishedItem newItem) {
2065:                service.getItemsToAdd().add(newItem);
2066:            }
2067:
2068:            /**
2069:             * Cancels any queued operation for the specified list of items. This operation is
2070:             * usually required when a node was deleted so any pending operation of the node items
2071:             * should be cancelled.
2072:             *
2073:             * @param service the PubSub service this action is to be performed for.
2074:             * @param items the list of items to remove the from queues.
2075:             */
2076:            void cancelQueuedItems(PubSubService service,
2077:                    Collection<PublishedItem> items) {
2078:                for (PublishedItem item : items) {
2079:                    service.getItemsToAdd().remove(item);
2080:                    service.getItemsToDelete().remove(item);
2081:                }
2082:            }
2083:
2084:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.