| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| */ |
| package org.apache.vysper.xmpp.modules.extension.xep0060_pubsub; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| import org.apache.vysper.compliance.SpecCompliant; |
| import org.apache.vysper.xmpp.addressing.Entity; |
| import org.apache.vysper.xmpp.addressing.EntityUtils; |
| import org.apache.vysper.xmpp.modules.DefaultDiscoAwareModule; |
| import org.apache.vysper.xmpp.modules.core.base.handler.MessageHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.PubSubCreateNodeHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.PubSubPublishHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.PubSubRetrieveAffiliationsHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.PubSubRetrieveSubscriptionsHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.PubSubSubscribeHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.PubSubUnsubscribeHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.owner.PubSubOwnerConfigureNodeHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.handler.owner.PubSubOwnerDeleteNodeHandler; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.model.CollectionNode; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.model.LeafNode; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.storageprovider.CollectionNodeStorageProvider; |
| import org.apache.vysper.xmpp.modules.extension.xep0060_pubsub.storageprovider.LeafNodeStorageProvider; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.ComponentInfoRequestListener; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.Feature; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.Identity; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.InfoElement; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.InfoRequest; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.Item; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.ItemRequestListener; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.ServerInfoRequestListener; |
| import org.apache.vysper.xmpp.modules.servicediscovery.management.ServiceDiscoveryRequestException; |
| import org.apache.vysper.xmpp.protocol.NamespaceHandlerDictionary; |
| import org.apache.vysper.xmpp.protocol.NamespaceURIs; |
| import org.apache.vysper.xmpp.protocol.StanzaHandler; |
| import org.apache.vysper.xmpp.protocol.StanzaProcessor; |
| import org.apache.vysper.xmpp.server.ServerRuntimeContext; |
| import org.apache.vysper.xmpp.server.components.Component; |
| import org.apache.vysper.xmpp.server.components.ComponentStanzaProcessor; |
| import org.slf4j.Logger; |
| import org.slf4j.LoggerFactory; |
| |
| /** |
| * Initializes the XEP0060 module. This class is also responsible for disco requests at the service level. |
| * |
| * @author The Apache MINA Project (http://mina.apache.org) |
| */ |
| @SpecCompliant(spec = "xep-0060", comment = "spec. version: 1.13rc", status = SpecCompliant.ComplianceStatus.IN_PROGRESS, coverage = SpecCompliant.ComplianceCoverage.PARTIAL) |
| public class PublishSubscribeModule extends DefaultDiscoAwareModule implements Component, ComponentInfoRequestListener, |
| ItemRequestListener { |
| |
| // The configuration of the service |
| private PubSubServiceConfiguration serviceConfiguration = null; |
| |
| // for debugging |
| private final Logger logger = LoggerFactory.getLogger(PublishSubscribeModule.class); |
| |
| private ComponentStanzaProcessor stanzaProcessor; |
| |
| private ServerRuntimeContext serverRuntimeContext; |
| |
| /** |
| * the subdomain this module becomes know under. |
| */ |
| protected String subdomain = "pubsub"; |
| |
| /** |
| * the domain derived from the subdomain and the server domain |
| */ |
| protected Entity fullDomain; |
| |
| /** |
| * Create a new PublishSubscribeModule together with a new root-collection node. |
| */ |
| public PublishSubscribeModule(String subdomain) { |
| this(); |
| this.subdomain = subdomain; |
| } |
| |
| /** |
| * Create a new PublishSubscribeModule together with a new root-collection node. |
| */ |
| public PublishSubscribeModule() { |
| this(new PubSubServiceConfiguration(new CollectionNode())); |
| } |
| |
| /** |
| * Create a new PublishSubscribeModule together with a supplied root-collection node. |
| */ |
| public PublishSubscribeModule(PubSubServiceConfiguration serviceConfiguration) { |
| this.serviceConfiguration = serviceConfiguration; |
| } |
| |
| /** |
| * Initializes the pubsub module, configuring the storage providers. |
| */ |
| @Override |
| public void initialize(ServerRuntimeContext serverRuntimeContext) { |
| super.initialize(serverRuntimeContext); |
| |
| this.serverRuntimeContext = serverRuntimeContext; |
| |
| fullDomain = EntityUtils.createComponentDomain(subdomain, serverRuntimeContext); |
| |
| CollectionNodeStorageProvider collectionNodeStorageProvider = serverRuntimeContext |
| .getStorageProvider(CollectionNodeStorageProvider.class); |
| LeafNodeStorageProvider leafNodeStorageProvider = serverRuntimeContext |
| .getStorageProvider(LeafNodeStorageProvider.class); |
| |
| if (collectionNodeStorageProvider == null) { |
| logger.warn("No collection node storage provider found, using the default (in memory)"); |
| } else { |
| serviceConfiguration.setCollectionNodeStorageProvider(collectionNodeStorageProvider); |
| } |
| |
| if (leafNodeStorageProvider == null) { |
| logger.warn("No leaf node storage provider found, using the default (in memory)"); |
| } else { |
| serviceConfiguration.setLeafNodeStorageProvider(leafNodeStorageProvider); |
| } |
| |
| ComponentStanzaProcessor processor = new ComponentStanzaProcessor(serverRuntimeContext); |
| addPubsubHandlers(processor); |
| addPubsubOwnerHandlers(processor); |
| processor |
| .addDictionary(new NamespaceHandlerDictionary(NamespaceURIs.XEP0060_PUBSUB_EVENT, new MessageHandler())); |
| stanzaProcessor = processor; |
| |
| this.serviceConfiguration.setDomainJID(fullDomain); |
| this.serviceConfiguration.initialize(); |
| } |
| |
| /** |
| * Returns the service name |
| */ |
| @Override |
| public String getName() { |
| return "XEP-0060 Publish-Subscribe"; |
| } |
| |
| /** |
| * Returns the implemented spec. version. |
| */ |
| @Override |
| public String getVersion() { |
| return "1.13rc3"; |
| } |
| |
| /** |
| * Implements the getServerInfosFor method from the {@link ServerInfoRequestListener} interface. |
| * Makes this modules available via disco#info as "pubsub service" in the pubsub namespace. |
| * |
| * @see ComponentInfoRequestListener#getComponentInfosFor(org.apache.vysper.xmpp.modules.servicediscovery.management.InfoRequest) |
| */ |
| public List<InfoElement> getComponentInfosFor(InfoRequest request) throws ServiceDiscoveryRequestException { |
| if (!EntityUtils.isAddressingServer(fullDomain, request.getTo())) |
| return null; |
| |
| CollectionNode root = serviceConfiguration.getRootNode(); |
| List<InfoElement> infoElements = new ArrayList<InfoElement>(); |
| if (request.getNode() == null || request.getNode().length() == 0) { |
| infoElements.add(new Identity("pubsub", "service", "Publish-Subscribe")); |
| infoElements.add(new Feature(NamespaceURIs.XEP0060_PUBSUB)); |
| } else { |
| LeafNode node = root.find(request.getNode()); |
| infoElements.addAll(node.getNodeInfosFor(request)); |
| } |
| return infoElements; |
| } |
| |
| @Override |
| protected void addComponentInfoRequestListeners(List<ComponentInfoRequestListener> componentInfoRequestListeners) { |
| componentInfoRequestListeners.add(this); |
| } |
| |
| /** |
| * Make this object available for disco#items requests. |
| */ |
| @Override |
| protected void addItemRequestListeners(List<ItemRequestListener> itemRequestListeners) { |
| itemRequestListeners.add(this); |
| } |
| |
| /** |
| * Implements the getItemsFor method from the {@link ItemRequestListener} interface. |
| * Makes this modules available via disco#items and returns the associated nodes. |
| * |
| * @see ItemRequestListener#getItemsFor(InfoRequest) |
| */ |
| public List<Item> getItemsFor(InfoRequest request) throws ServiceDiscoveryRequestException { |
| CollectionNode root = serviceConfiguration.getRootNode(); |
| List<Item> items = null; |
| |
| if (request.getNode() == null || request.getNode().length() == 0) { |
| if (serverRuntimeContext.getServerEnitity().equals(request.getTo())) { |
| // top level item request. for example return entry for "pubsub.vysper.org" on request for "vysper.org" |
| List<Item> componentItem = new ArrayList<Item>(); |
| componentItem.add(new Item(fullDomain)); |
| return componentItem; |
| } else if (!fullDomain.equals(request.getTo())) { |
| return null; // not in component's domain |
| } |
| ServiceDiscoItemsVisitor nv = new ServiceDiscoItemsVisitor(serviceConfiguration); |
| root.acceptNodes(nv); |
| items = nv.getNodeItemList(); |
| } else { |
| LeafNode node = root.find(request.getNode()); |
| NodeDiscoItemsVisitor iv = new NodeDiscoItemsVisitor(request.getTo()); |
| node.acceptItems(iv); |
| items = iv.getItemList(); |
| } |
| |
| return items; |
| } |
| |
| /** |
| * Inserts the handlers for the pubsub#owner namespace into the HandlerDictionary. |
| * @param dictionary the list to which the handlers should be appended. |
| */ |
| private void addPubsubOwnerHandlers(ComponentStanzaProcessor dictionary) { |
| ArrayList<StanzaHandler> pubsubOwnerHandlers = new ArrayList<StanzaHandler>(); |
| pubsubOwnerHandlers.add(new PubSubOwnerConfigureNodeHandler(serviceConfiguration)); |
| pubsubOwnerHandlers.add(new PubSubOwnerDeleteNodeHandler(serviceConfiguration)); |
| dictionary |
| .addDictionary(new NamespaceHandlerDictionary(NamespaceURIs.XEP0060_PUBSUB_OWNER, pubsubOwnerHandlers)); |
| } |
| |
| /** |
| * Inserts the handlers for the pubsub namespace into the HandlerDictionary. |
| * @param dictionary the list to which the handlers should be appended. |
| */ |
| private void addPubsubHandlers(ComponentStanzaProcessor dictionary) { |
| ArrayList<StanzaHandler> pubsubHandlers = new ArrayList<StanzaHandler>(); |
| pubsubHandlers.add(new PubSubSubscribeHandler(serviceConfiguration)); |
| pubsubHandlers.add(new PubSubUnsubscribeHandler(serviceConfiguration)); |
| pubsubHandlers.add(new PubSubPublishHandler(serviceConfiguration)); |
| pubsubHandlers.add(new PubSubCreateNodeHandler(serviceConfiguration)); |
| pubsubHandlers.add(new PubSubRetrieveSubscriptionsHandler(serviceConfiguration)); |
| pubsubHandlers.add(new PubSubRetrieveAffiliationsHandler(serviceConfiguration)); |
| dictionary.addDictionary(new NamespaceHandlerDictionary(NamespaceURIs.XEP0060_PUBSUB, pubsubHandlers)); |
| } |
| |
| public String getSubdomain() { |
| return subdomain; |
| } |
| |
| public StanzaProcessor getStanzaProcessor() { |
| return stanzaProcessor; |
| } |
| } |