This is an automated email from the ASF dual-hosted git repository. ralaoui pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/mina-vysper.git
The following commit(s) were added to refs/heads/master by this push: new cdc4c53 Remove getComponentStanzaProcessor from the ServerRuntimeContext cdc4c53 is described below commit cdc4c534c4b44a433b8aea2e02313b2686f43384 Author: Réda Housni Alaoui <reda.housniala...@gmail.com> AuthorDate: Sat Aug 24 22:50:59 2019 +0200 Remove getComponentStanzaProcessor from the ServerRuntimeContext --- ...pringCompatibleDefaultServerRuntimeContext.java | 6 +- .../DeliveringInternalInboundStanzaRelay.java | 18 +- .../handler/DiscoInfoIQHandler.java | 2 +- .../handler/DiscoItemIQHandler.java | 2 +- .../xmpp/server/AlterableComponentRegistry.java | 31 ++++ .../vysper/xmpp/server/ComponentRegistry.java | 32 ++++ .../xmpp/server/DefaultServerRuntimeContext.java | 143 +++++++++------ .../vysper/xmpp/server/ServerRuntimeContext.java | 2 +- .../xmpp/server/SimpleComponentRegistry.java | 66 +++++++ .../org/apache/vysper/xmpp/server/XMPPServer.java | 87 +++++---- .../stanzasession/StanzaSessionTestCase.java | 7 +- ...eliveringInteralInboundStanzaRelayTestCase.java | 27 ++- .../handler/DiscoInfoIQHandlerTestCase.java | 204 +++++++++++---------- .../handler/ExtendedDiscoInfoTestCase.java | 3 +- .../ProtocolWorkerStateAwarenessTestCase.java | 3 +- ...faultServerRuntimeContextEventListenerTest.java | 3 +- 16 files changed, 407 insertions(+), 229 deletions(-) diff --git a/server/core/src/main/java/org/apache/vysper/spring/SpringCompatibleDefaultServerRuntimeContext.java b/server/core/src/main/java/org/apache/vysper/spring/SpringCompatibleDefaultServerRuntimeContext.java index 4fc5e26..44876a2 100644 --- a/server/core/src/main/java/org/apache/vysper/spring/SpringCompatibleDefaultServerRuntimeContext.java +++ b/server/core/src/main/java/org/apache/vysper/spring/SpringCompatibleDefaultServerRuntimeContext.java @@ -28,6 +28,7 @@ import org.apache.vysper.xmpp.delivery.failure.DeliveryFailureStrategy; import org.apache.vysper.xmpp.delivery.failure.ServiceNotAvailableException; import org.apache.vysper.xmpp.modules.Module; import org.apache.vysper.xmpp.protocol.HandlerDictionary; +import org.apache.vysper.xmpp.server.AlterableComponentRegistry; import org.apache.vysper.xmpp.server.DefaultServerRuntimeContext; import org.apache.vysper.xmpp.server.ServerFeatures; import org.apache.vysper.xmpp.stanza.Stanza; @@ -63,8 +64,9 @@ public class SpringCompatibleDefaultServerRuntimeContext extends DefaultServerRu } public SpringCompatibleDefaultServerRuntimeContext(Entity serverEntity, ServerFeatures serverFeatures, - List<HandlerDictionary> dictionaries, ResourceRegistry resourceRegistry) { - super(serverEntity, new StanzaRelayHull(), serverFeatures, dictionaries, resourceRegistry); + List<HandlerDictionary> dictionaries, ResourceRegistry resourceRegistry, + AlterableComponentRegistry componentRegistry) { + super(serverEntity, new StanzaRelayHull(), componentRegistry, resourceRegistry, serverFeatures, dictionaries); } public void setStanzaRelay(StanzaRelay stanzaRelay) { diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java b/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java index fca397b..49fb761 100644 --- a/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java +++ b/server/core/src/main/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInternalInboundStanzaRelay.java @@ -19,6 +19,8 @@ */ package org.apache.vysper.xmpp.delivery.inbound; +import static java.util.Objects.requireNonNull; + import java.io.IOException; import java.io.Writer; import java.util.List; @@ -49,9 +51,11 @@ import org.apache.vysper.xmpp.protocol.SessionStateHolder; import org.apache.vysper.xmpp.protocol.StanzaHandler; import org.apache.vysper.xmpp.protocol.StanzaProcessor; import org.apache.vysper.xmpp.protocol.worker.InboundStanzaProtocolWorker; +import org.apache.vysper.xmpp.server.ComponentRegistry; import org.apache.vysper.xmpp.server.ServerRuntimeContext; import org.apache.vysper.xmpp.server.SessionContext; import org.apache.vysper.xmpp.server.SessionState; +import org.apache.vysper.xmpp.server.SimpleComponentRegistry; import org.apache.vysper.xmpp.server.resources.ManagedThreadPool; import org.apache.vysper.xmpp.server.resources.ManagedThreadPoolUtil; import org.apache.vysper.xmpp.stanza.IQStanza; @@ -94,6 +98,8 @@ public class DeliveringInternalInboundStanzaRelay implements StanzaRelay, Manage private InboundStanzaProtocolWorker inboundStanzaProtocolWorker; + private final ComponentRegistry componentRegistry; + private static final Integer PRIO_THRESHOLD = 0; protected ResourceRegistry resourceRegistry; @@ -115,15 +121,18 @@ public class DeliveringInternalInboundStanzaRelay implements StanzaRelay, Manage protected long lastDumpTimestamp = 0; public DeliveringInternalInboundStanzaRelay(Entity serverEntity, ResourceRegistry resourceRegistry, - StorageProviderRegistry storageProviderRegistry) { - this(serverEntity, resourceRegistry, storageProviderRegistry.retrieve(AccountManagement.class), + StorageProviderRegistry storageProviderRegistry, ComponentRegistry componentRegistry) { + this(serverEntity, resourceRegistry, componentRegistry, + storageProviderRegistry.retrieve(AccountManagement.class), storageProviderRegistry.retrieve(OfflineStorageProvider.class)); } public DeliveringInternalInboundStanzaRelay(Entity serverEntity, ResourceRegistry resourceRegistry, - AccountManagement accountVerification, OfflineStanzaReceiver offlineStanzaReceiver) { + ComponentRegistry componentRegistry, AccountManagement accountVerification, + OfflineStanzaReceiver offlineStanzaReceiver) { this.serverEntity = serverEntity; this.resourceRegistry = resourceRegistry; + this.componentRegistry = requireNonNull(componentRegistry); this.accountVerification = accountVerification; this.offlineStanzaReceiver = offlineStanzaReceiver; int coreThreadCount = 10; @@ -134,6 +143,7 @@ public class DeliveringInternalInboundStanzaRelay implements StanzaRelay, Manage } /* package */ DeliveringInternalInboundStanzaRelay(ExecutorService executor) { + this.componentRegistry = null; this.executor = executor; } @@ -269,7 +279,7 @@ public class DeliveringInternalInboundStanzaRelay implements StanzaRelay, Manage new ServiceNotAvailableException("unsupported domain " + receiverDomain)); } - StanzaProcessor processor = serverRuntimeContext.getComponentStanzaProcessor(receiver); + StanzaProcessor processor = componentRegistry.getComponentStanzaProcessor(receiver); if (processor == null) { return new RelayResult(new ServiceNotAvailableException( "cannot retrieve component stanza processor for" + receiverDomain)); diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java b/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java index 0834b8d..a498704 100644 --- a/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java +++ b/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandler.java @@ -98,7 +98,7 @@ public class DiscoInfoIQHandler extends DefaultIQHandler { Entity serverEntity = serverRuntimeContext.getServerEntity(); if (to == null || to.equals(serverEntity)) { isServerInfoRequest = true; // this can only be meant to query the server - } else if (serverRuntimeContext.getComponentStanzaProcessor(to) != null) { + } else if (serverRuntimeContext.hasComponentStanzaProcessor(to)) { isComponentInfoRequest = true; // this is a query to a component } else if (!to.isNodeSet()) { isServerInfoRequest = serverEntity.equals(to); diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoItemIQHandler.java b/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoItemIQHandler.java index 4f87614..0ba4b32 100644 --- a/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoItemIQHandler.java +++ b/server/core/src/main/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoItemIQHandler.java @@ -91,7 +91,7 @@ public class DiscoItemIQHandler extends DefaultIQHandler { isServerInfoRequest = true; // this can only be meant to query the server } else if (!to.isNodeSet()) { isServerInfoRequest = serverRuntimeContext.getServerEntity().equals(to); - isComponentInfoRequest = serverRuntimeContext.getComponentStanzaProcessor(to) != null; + isComponentInfoRequest = serverRuntimeContext.hasComponentStanzaProcessor(to); if (!isServerInfoRequest && !isComponentInfoRequest) { return Collections.singletonList(ServerErrorResponses.getStanzaError(StanzaErrorCondition.ITEM_NOT_FOUND, stanza, StanzaErrorType.CANCEL, diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/server/AlterableComponentRegistry.java b/server/core/src/main/java/org/apache/vysper/xmpp/server/AlterableComponentRegistry.java new file mode 100644 index 0000000..f4ff214 --- /dev/null +++ b/server/core/src/main/java/org/apache/vysper/xmpp/server/AlterableComponentRegistry.java @@ -0,0 +1,31 @@ +/* + * 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.server; + +import org.apache.vysper.xmpp.server.components.Component; + +/** + * @author Réda Housni Alaoui + */ +public interface AlterableComponentRegistry extends ComponentRegistry { + + void registerComponent(Component component); + +} diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/server/ComponentRegistry.java b/server/core/src/main/java/org/apache/vysper/xmpp/server/ComponentRegistry.java new file mode 100644 index 0000000..cd97b55 --- /dev/null +++ b/server/core/src/main/java/org/apache/vysper/xmpp/server/ComponentRegistry.java @@ -0,0 +1,32 @@ +/* + * 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.server; + +import org.apache.vysper.xmpp.addressing.Entity; +import org.apache.vysper.xmpp.protocol.StanzaProcessor; + +/** + * @author Réda Housni Alaoui + */ +public interface ComponentRegistry { + + StanzaProcessor getComponentStanzaProcessor(Entity entity); + +} diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java b/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java index 93ff22d..83b1edb 100644 --- a/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java +++ b/server/core/src/main/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContext.java @@ -20,6 +20,8 @@ package org.apache.vysper.xmpp.server; +import static java.util.Objects.requireNonNull; + import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; @@ -34,7 +36,6 @@ import org.apache.vysper.storage.OpenStorageProviderRegistry; import org.apache.vysper.storage.StorageProvider; import org.apache.vysper.storage.StorageProviderRegistry; import org.apache.vysper.xmpp.addressing.Entity; -import org.apache.vysper.xmpp.addressing.EntityUtils; import org.apache.vysper.xmpp.authentication.UserAuthentication; import org.apache.vysper.xmpp.cryptography.TLSContextFactory; import org.apache.vysper.xmpp.delivery.StanzaRelay; @@ -83,7 +84,7 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module /** * feature configuration */ - private ServerFeatures serverFeatures = new ServerFeatures(); + private final ServerFeatures serverFeatures; /** * the Secure Socket Engine in use @@ -93,17 +94,19 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module /** * generates unique session ids */ - private UUIDGenerator sessionIdGenerator = new JVMBuiltinUUIDGenerator(); + private final UUIDGenerator sessionIdGenerator = new JVMBuiltinUUIDGenerator(); // basic services the server is using... /** - * 'input stream': receives stanzas issued by client sessions to be handled by the server + * 'input stream': receives stanzas issued by client sessions to be handled by + * the server */ private final StanzaProcessor stanzaProcessor; /** - * 'output stream': receives stanzas issued by a session, which are going to other sessions/servers + * 'output stream': receives stanzas issued by a session, which are going to + * other sessions/servers */ private final StanzaRelay stanzaRelay; @@ -118,34 +121,42 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module private LatestPresenceCache presenceCache = new SimplePresenceCache(); private final XMPPServerConnectorRegistry serverConnectorRegistry; - + /** * holds the storage services */ private StorageProviderRegistry storageProviderRegistry = new OpenStorageProviderRegistry(); /** - * collection of all other services, which are mostly add-ons to the minimal setup + * collection of all other services, which are mostly add-ons to the minimal + * setup */ private final Map<String, ServerRuntimeContextService> serverRuntimeContextServiceMap = new HashMap<String, ServerRuntimeContextService>(); private List<Module> modules = new ArrayList<Module>(); - + /** - * map of all registered components, index by the subdomain they are registered for + * map of all registered components, index by the subdomain they are registered + * for */ - protected final Map<String, Component> componentMap = new HashMap<String, Component>(); - + private final AlterableComponentRegistry componentRegistry; + private final SimpleEventBus eventBus; - public DefaultServerRuntimeContext(Entity serverEntity, StanzaRelay stanzaRelay) { + public DefaultServerRuntimeContext(Entity serverEntity, StanzaRelay stanzaRelay, + AlterableComponentRegistry componentRegistry, ResourceRegistry resourceRegistry, + ServerFeatures serverFeatures, List<HandlerDictionary> dictionaries) { this.serverEntity = serverEntity; this.stanzaRelay = stanzaRelay; this.stanzaProcessor = new ProtocolWorker(stanzaRelay); - this.resourceRegistry = new DefaultResourceRegistry(); + this.componentRegistry = requireNonNull(componentRegistry); this.serverConnectorRegistry = new DefaultXMPPServerConnectorRegistry(this, stanzaRelay); this.stanzaHandlerLookup = new StanzaHandlerLookup(this); this.eventBus = new SimpleEventBus(); + this.serverFeatures = serverFeatures; + this.resourceRegistry = resourceRegistry; + + addDictionaries(dictionaries); } public DefaultServerRuntimeContext(Entity serverEntity, StanzaRelay stanzaRelay, @@ -154,18 +165,15 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module this.storageProviderRegistry = storageProviderRegistry; } - public DefaultServerRuntimeContext(Entity serverEntity, StanzaRelay stanzaRelay, ServerFeatures serverFeatures, - List<HandlerDictionary> dictionaries, ResourceRegistry resourceRegistry) { - this(serverEntity, stanzaRelay); - this.serverFeatures = serverFeatures; - this.resourceRegistry = resourceRegistry; - - addDictionaries(dictionaries); + public DefaultServerRuntimeContext(Entity serverEntity, StanzaRelay stanzaRelay) { + this(serverEntity, stanzaRelay, new SimpleComponentRegistry(serverEntity), new DefaultResourceRegistry(), + new ServerFeatures(), Collections.emptyList()); } /** - * change the presence cache implementation. this is a setter intended to be used at - * initialisation time. (thus, this method is not part of ServerRuntimeContext. + * change the presence cache implementation. this is a setter intended to be + * used at initialisation time. (thus, this method is not part of + * ServerRuntimeContext. * * @param presenceCache */ @@ -173,22 +181,27 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module this.presenceCache = presenceCache; } + @Override public StanzaHandler getHandler(Stanza stanza) { return stanzaHandlerLookup.getHandler(stanza); } + @Override public String getNextSessionId() { return sessionIdGenerator.create(); } + @Override public Entity getServerEntity() { return serverEntity; } + @Override public String getDefaultXMLLang() { return "en_US"; // TODO must be configurable as of RFC3920 } + @Override public StanzaProcessor getStanzaProcessor() { return stanzaProcessor; } @@ -197,10 +210,12 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module return stanzaRelay; } + @Override public ServerFeatures getServerFeatures() { return serverFeatures; } + @Override public XMPPServerConnectorRegistry getServerConnectorRegistry() { return serverConnectorRegistry; } @@ -223,29 +238,36 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module } } + @Override public SSLContext getSslContext() { return sslContext; } /** - * @deprecated use {@link #getStorageProvider(Class)} with {@link UserAuthentication}.class instead + * @deprecated use {@link #getStorageProvider(Class)} with + * {@link UserAuthentication}.class instead */ + @Override public UserAuthentication getUserAuthentication() { - return (UserAuthentication) storageProviderRegistry.retrieve(UserAuthentication.class); + return storageProviderRegistry.retrieve(UserAuthentication.class); } + @Override public ResourceRegistry getResourceRegistry() { return resourceRegistry; } + @Override public LatestPresenceCache getPresenceCache() { return presenceCache; } /** * add a runtime service. makes the service dynamically discoverable at runtime. + * * @param service */ + @Override public void registerServerRuntimeContextService(ServerRuntimeContextService service) { if (service == null) throw new IllegalStateException("service must not be null"); @@ -256,10 +278,11 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module } /** - * retrieves a previously registered runtime context service. The RosterManager is a good example of such a service. - * This allows for modules, extensions and other services to discover their dependencies at runtime. - * - * @see org.apache.vysper.xmpp.server.DefaultServerRuntimeContext#getStorageProvider(Class) + * retrieves a previously registered runtime context service. The RosterManager + * is a good example of such a service. This allows for modules, extensions and + * other services to discover their dependencies at runtime. + * + * @see org.apache.vysper.xmpp.server.DefaultServerRuntimeContext#getStorageProvider(Class) * @param name * @return */ @@ -270,6 +293,7 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module /** * adds a whole set of storage providers at once to the system. + * * @param storageProviderRegistry */ public void setStorageProviderRegistry(StorageProviderRegistry storageProviderRegistry) { @@ -279,26 +303,31 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module } /** - * retrieves a particular storage provider. + * retrieves a particular storage provider. + * * @param clazz * @return */ + @Override public <T extends StorageProvider> T getStorageProvider(Class<T> clazz) { return storageProviderRegistry.retrieve(clazz); } /** - * adds and initializes a list of Modules. A module extends the server's functionality by adding an - * XMPP extension ('XEP') to it. (More) Modules can be added at runtime. - * This approach has an advantage over adding modules one by one, in that it allows for a better - * dependency management: all modules from the list to first discover each other before initialize() - * get's called for every one of them. - * + * adds and initializes a list of Modules. A module extends the server's + * functionality by adding an XMPP extension ('XEP') to it. (More) Modules can + * be added at runtime. This approach has an advantage over adding modules one + * by one, in that it allows for a better dependency management: all modules + * from the list to first discover each other before initialize() get's called + * for every one of them. + * * @see org.apache.vysper.xmpp.server.DefaultServerRuntimeContext#registerServerRuntimeContextService(org.apache.vysper.xmpp.modules.ServerRuntimeContextService) - * @see org.apache.vysper.xmpp.server.DefaultServerRuntimeContext#getServerRuntimeContextService(String) + * @see org.apache.vysper.xmpp.server.DefaultServerRuntimeContext#getServerRuntimeContextService(String) * @see org.apache.vysper.xmpp.modules.Module - * @param modules List of modules + * @param modules + * List of modules */ + @Override public void addModules(List<Module> modules) { for (Module module : modules) { addModuleInternal(module); @@ -309,12 +338,15 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module } /** - * adds and initializes a single Module. a module extends the server's functionality by adding an - * XMPP extension ('XEP') to it. + * adds and initializes a single Module. a module extends the server's + * functionality by adding an XMPP extension ('XEP') to it. + * * @see org.apache.vysper.xmpp.modules.Module - * @see DefaultServerRuntimeContext#addModules(java.util.List) for adding a number of modules at once + * @see DefaultServerRuntimeContext#addModules(java.util.List) for adding a + * number of modules at once * @param module */ + @Override public void addModule(Module module) { addModuleInternal(module); module.initialize(this); @@ -329,7 +361,7 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module for (ServerRuntimeContextService serverRuntimeContextService : serviceList) { registerServerRuntimeContextService(serverRuntimeContextService); - // if a storage service, also register there + // if a storage service, also register there if (serverRuntimeContextService instanceof StorageProvider) { StorageProvider storageProvider = (StorageProvider) serverRuntimeContextService; storageProviderRegistry.add(storageProvider); @@ -351,17 +383,20 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module if (module instanceof Component) { registerComponent((Component) module); } - + modules.add(module); } - + + @Override public List<Module> getModules() { return Collections.unmodifiableList(modules); } + @Override public <T> T getModule(Class<T> clazz) { - for(Module module : modules) { - if(module.getClass().equals(clazz)) return (T) module; + for (Module module : modules) { + if (module.getClass().equals(clazz)) + return (T) module; } return null; } @@ -371,21 +406,14 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module return eventBus; } + @Override public void registerComponent(Component component) { - componentMap.put(component.getSubdomain(), component); + componentRegistry.registerComponent(component); } - public StanzaProcessor getComponentStanzaProcessor(Entity entity) { - String serverDomain = getServerEntity().getDomain(); - if (!EntityUtils.isAddressingServerComponent(entity, getServerEntity())) { - return null; - } - String domain = entity.getDomain(); - String subdomain = domain.replace("." + serverDomain, ""); - Component component = componentMap.get(subdomain); - if (component == null) - return null; - return component.getStanzaProcessor(); + @Override + public boolean hasComponentStanzaProcessor(Entity entity) { + return componentRegistry.getComponentStanzaProcessor(entity) != null; } @Override @@ -393,5 +421,4 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module return new ComponentStanzaProcessor(stanzaRelay); } - } diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerRuntimeContext.java b/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerRuntimeContext.java index a7897f4..9a1563b 100644 --- a/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerRuntimeContext.java +++ b/server/core/src/main/java/org/apache/vysper/xmpp/server/ServerRuntimeContext.java @@ -74,7 +74,7 @@ public interface ServerRuntimeContext { void registerComponent(Component component); - StanzaProcessor getComponentStanzaProcessor(Entity entity); + boolean hasComponentStanzaProcessor(Entity entity); ComponentStanzaProcessor createComponentStanzaProcessor(); diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/server/SimpleComponentRegistry.java b/server/core/src/main/java/org/apache/vysper/xmpp/server/SimpleComponentRegistry.java new file mode 100644 index 0000000..d2df521 --- /dev/null +++ b/server/core/src/main/java/org/apache/vysper/xmpp/server/SimpleComponentRegistry.java @@ -0,0 +1,66 @@ +/* + * 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.server; + +import org.apache.vysper.xmpp.addressing.Entity; +import org.apache.vysper.xmpp.addressing.EntityUtils; +import org.apache.vysper.xmpp.protocol.StanzaProcessor; +import org.apache.vysper.xmpp.server.components.Component; + +import java.util.HashMap; +import java.util.Map; + +import static java.util.Objects.requireNonNull; + +/** + * @author Réda Housni Alaoui + */ +public class SimpleComponentRegistry implements AlterableComponentRegistry { + + private final Entity serverEntity; + + /** + * map of all registered components, index by the subdomain they are registered for + */ + private final Map<String, Component> componentMap = new HashMap<>(); + + public SimpleComponentRegistry(Entity serverEntity) { + this.serverEntity = requireNonNull(serverEntity); + } + + @Override + public void registerComponent(Component component){ + componentMap.put(component.getSubdomain(), component); + } + + @Override + public StanzaProcessor getComponentStanzaProcessor(Entity entity) { + String serverDomain = serverEntity.getDomain(); + if (!EntityUtils.isAddressingServerComponent(entity, serverEntity)) { + return null; + } + String domain = entity.getDomain(); + String subdomain = domain.replace("." + serverDomain, ""); + Component component = componentMap.get(subdomain); + if (component == null) + return null; + return component.getStanzaProcessor(); + } +} diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/server/XMPPServer.java b/server/core/src/main/java/org/apache/vysper/xmpp/server/XMPPServer.java index 664624d..5268bc9 100644 --- a/server/core/src/main/java/org/apache/vysper/xmpp/server/XMPPServer.java +++ b/server/core/src/main/java/org/apache/vysper/xmpp/server/XMPPServer.java @@ -51,8 +51,7 @@ import org.apache.vysper.xmpp.state.resourcebinding.DefaultResourceRegistry; import org.apache.vysper.xmpp.state.resourcebinding.ResourceRegistry; /** - * this class is able to boot a standalone XMPP server. - * <code> + * this class is able to boot a standalone XMPP server. <code> * XMPPServer server = new XMPPServer("vysper.org"); * * server.addEndpoint(...); // add endpoints, at least one @@ -69,10 +68,10 @@ public class XMPPServer { private String serverDomain; - private ServerRuntimeContext serverRuntimeContext; + private DefaultServerRuntimeContext serverRuntimeContext; private StorageProviderRegistry storageProviderRegistry; - + private StanzaRelayBroker stanzaRelayBroker; private InputStream tlsCertificate; @@ -84,9 +83,9 @@ public class XMPPServer { private final List<Endpoint> endpoints = new ArrayList<Endpoint>(); private final List<Module> initialModules = new ArrayList<Module>(); - + private int maxInternalRelayThreads = -1; - + private int maxExternalRelayThreads = -1; public XMPPServer(String domain) { @@ -94,7 +93,8 @@ public class XMPPServer { throw new IllegalArgumentException("server domain cannot be blank, empty or NULL"); } if (!domain.equals(domain.toLowerCase())) { - throw new IllegalArgumentException("server domain must be given in all lower-case letters, but was: " + domain); + throw new IllegalArgumentException( + "server domain must be given in all lower-case letters, but was: " + domain); } try { EntityImpl.parse(domain); @@ -105,7 +105,7 @@ public class XMPPServer { // default list of SASL mechanisms saslMechanisms.add(new Plain()); - + // add default modules initialModules.add(new ServiceDiscoveryModule()); initialModules.add(new RosterModule()); @@ -126,13 +126,13 @@ public class XMPPServer { } public void setTLSCertificateInfo(InputStream certificate, String password) { - setTLSCertificateInfo(certificate, password, null); + setTLSCertificateInfo(certificate, password, null); } public void setTLSCertificateInfo(InputStream certificate, String password, String keyStoreType) { - tlsCertificate = certificate; - tlsCertificatePassword = password; - tlsKeyStoreType = keyStoreType; + tlsCertificate = certificate; + tlsCertificatePassword = password; + tlsKeyStoreType = keyStoreType; } public void setMaxInternalRelayThreads(int maxInternalRelayThreads) { @@ -154,7 +154,7 @@ public class XMPPServer { TrustManagerFactory trustManagerFactory = null; // default, check certificates strictly if (!serverFeatures.isCheckingFederationServerCertificates()) { - // switch to accepting *any* certificate + // switch to accepting *any* certificate trustManagerFactory = new NonCheckingX509TrustManagerFactory(); } @@ -164,8 +164,8 @@ public class XMPPServer { InputStreamBasedTLSContextFactory tlsContextFactory = new InputStreamBasedTLSContextFactory(tlsCertificate); tlsContextFactory.setPassword(tlsCertificatePassword); tlsContextFactory.setTrustManagerFactory(trustManagerFactory); - if(tlsKeyStoreType != null) { - tlsContextFactory.setKeyStoreType(tlsKeyStoreType); + if (tlsKeyStoreType != null) { + tlsContextFactory.setKeyStoreType(tlsKeyStoreType); } List<HandlerDictionary> dictionaries = new ArrayList<HandlerDictionary>(); @@ -175,22 +175,29 @@ public class XMPPServer { EntityImpl serverEntity = new EntityImpl(null, serverDomain, null); - AccountManagement accountManagement = storageProviderRegistry - .retrieve(AccountManagement.class); + AccountManagement accountManagement = storageProviderRegistry.retrieve(AccountManagement.class); OfflineStanzaReceiver offlineReceiver = storageProviderRegistry.retrieve(OfflineStorageProvider.class); - DeliveringInternalInboundStanzaRelay internalStanzaRelay = new DeliveringInternalInboundStanzaRelay(serverEntity, - resourceRegistry, accountManagement,offlineReceiver); + + AlterableComponentRegistry componentRegistry = new SimpleComponentRegistry(serverEntity); + + DeliveringInternalInboundStanzaRelay internalStanzaRelay = new DeliveringInternalInboundStanzaRelay( + serverEntity, resourceRegistry, componentRegistry, accountManagement, offlineReceiver); DeliveringExternalInboundStanzaRelay externalStanzaRelay = new DeliveringExternalInboundStanzaRelay(); - - if (maxInternalRelayThreads >= 0) internalStanzaRelay.setMaxThreadCount(maxInternalRelayThreads); - if (maxExternalRelayThreads >= 0) externalStanzaRelay.setMaxThreadCount(maxExternalRelayThreads); + + if (maxInternalRelayThreads >= 0) + internalStanzaRelay.setMaxThreadCount(maxInternalRelayThreads); + if (maxExternalRelayThreads >= 0) + externalStanzaRelay.setMaxThreadCount(maxExternalRelayThreads); stanzaRelayBroker = new StanzaRelayBroker(); stanzaRelayBroker.setInternalRelay(internalStanzaRelay); stanzaRelayBroker.setExternalRelay(externalStanzaRelay); - serverRuntimeContext = createServerRuntimeContext(serverFeatures, tlsContextFactory, dictionaries, - resourceRegistry, serverEntity); + serverRuntimeContext = new DefaultServerRuntimeContext(serverEntity, stanzaRelayBroker, componentRegistry, + resourceRegistry, serverFeatures, dictionaries); + serverRuntimeContext.setStorageProviderRegistry(storageProviderRegistry); + serverRuntimeContext.setTlsContextFactory(tlsContextFactory); + for (Module module : initialModules) { serverRuntimeContext.addModule(module); } @@ -200,28 +207,18 @@ public class XMPPServer { internalStanzaRelay.setStanzaRelay(stanzaRelayBroker); externalStanzaRelay.setServerRuntimeContext(serverRuntimeContext); - final LogStorageProvider logStorageProvider = - (LogStorageProvider) this.storageProviderRegistry.retrieve(LogStorageProvider.class); - if (logStorageProvider != null) internalStanzaRelay.setLogStorageProvider(logStorageProvider); + final LogStorageProvider logStorageProvider = this.storageProviderRegistry.retrieve(LogStorageProvider.class); + if (logStorageProvider != null) + internalStanzaRelay.setLogStorageProvider(logStorageProvider); - if (endpoints.size() == 0) throw new IllegalStateException("server must have at least one endpoint"); + if (endpoints.size() == 0) + throw new IllegalStateException("server must have at least one endpoint"); for (Endpoint endpoint : endpoints) { endpoint.setServerRuntimeContext(serverRuntimeContext); endpoint.start(); } } - protected ServerRuntimeContext createServerRuntimeContext(ServerFeatures serverFeatures, - InputStreamBasedTLSContextFactory tlsContextFactory, List<HandlerDictionary> dictionaries, - ResourceRegistry resourceRegistry, EntityImpl serverEntity) { - DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(serverEntity, - stanzaRelayBroker, serverFeatures, dictionaries, resourceRegistry); - serverRuntimeContext.setStorageProviderRegistry(storageProviderRegistry); - serverRuntimeContext.setTlsContextFactory(tlsContextFactory); - - return serverRuntimeContext; - } - protected ServerFeatures createServerFeatures() { return new ServerFeatures(); } @@ -230,21 +227,21 @@ public class XMPPServer { for (Endpoint endpoint : endpoints) { endpoint.stop(); } - - for(Module module : serverRuntimeContext.getModules()) { + + for (Module module : serverRuntimeContext.getModules()) { try { module.close(); - } catch(RuntimeException e) { + } catch (RuntimeException e) { // ignore } } - + stanzaRelayBroker.stop(); serverRuntimeContext.getServerConnectorRegistry().close(); } public void addModule(Module module) { - if(serverRuntimeContext != null) { + if (serverRuntimeContext != null) { serverRuntimeContext.addModule(module); } else { initialModules.add(module); @@ -259,7 +256,7 @@ public class XMPPServer { dictionaries.add(new org.apache.vysper.xmpp.modules.core.session.SessionStanzaDictionary()); dictionaries.add(new org.apache.vysper.xmpp.modules.core.compatibility.jabber_iq_auth.JabberIQAuthDictionary()); } - + public ServerRuntimeContext getServerRuntimeContext() { return serverRuntimeContext; } diff --git a/server/core/src/test/java/org/apache/vysper/stanzasession/StanzaSessionTestCase.java b/server/core/src/test/java/org/apache/vysper/stanzasession/StanzaSessionTestCase.java index 30e505a..e0af08c 100644 --- a/server/core/src/test/java/org/apache/vysper/stanzasession/StanzaSessionTestCase.java +++ b/server/core/src/test/java/org/apache/vysper/stanzasession/StanzaSessionTestCase.java @@ -24,11 +24,13 @@ import java.util.List; import junit.framework.TestCase; +import org.apache.vysper.xmpp.addressing.Entity; import org.apache.vysper.xmpp.addressing.EntityImpl; import org.apache.vysper.xmpp.delivery.StanzaRelayBroker; import org.apache.vysper.xmpp.protocol.HandlerDictionary; import org.apache.vysper.xmpp.server.DefaultServerRuntimeContext; import org.apache.vysper.xmpp.server.ServerFeatures; +import org.apache.vysper.xmpp.server.SimpleComponentRegistry; import org.apache.vysper.xmpp.stanza.Stanza; import org.apache.vysper.xmpp.stanza.StanzaBuilder; import org.apache.vysper.xmpp.state.resourcebinding.DefaultResourceRegistry; @@ -53,8 +55,9 @@ public class StanzaSessionTestCase extends TestCase { dictionaries.add(new org.apache.vysper.xmpp.modules.core.compatibility.jabber_iq_auth.JabberIQAuthDictionary()); dictionaries.add(new org.apache.vysper.xmpp.modules.roster.RosterDictionary()); - DefaultServerRuntimeContext serverContext = new DefaultServerRuntimeContext(new EntityImpl(null, "test", null), - relay, new ServerFeatures(), dictionaries, new DefaultResourceRegistry()); + Entity serverEntity = new EntityImpl(null, "test", null); + DefaultServerRuntimeContext serverContext = new DefaultServerRuntimeContext(serverEntity, + relay, new SimpleComponentRegistry(serverEntity), new DefaultResourceRegistry(), new ServerFeatures(), dictionaries); relay.setServerRuntimeContext(serverContext); diff --git a/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java b/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java index 6b9e4b1..05c42eb 100644 --- a/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java +++ b/server/core/src/test/java/org/apache/vysper/xmpp/delivery/inbound/DeliveringInteralInboundStanzaRelayTestCase.java @@ -19,6 +19,8 @@ */ package org.apache.vysper.xmpp.delivery.inbound; +import static org.mockito.Mockito.mock; + import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -34,6 +36,7 @@ import org.apache.vysper.xmpp.delivery.failure.IgnoreFailureStrategy; import org.apache.vysper.xmpp.delivery.failure.ServiceNotAvailableException; import org.apache.vysper.xmpp.server.DefaultServerRuntimeContext; import org.apache.vysper.xmpp.server.SessionState; +import org.apache.vysper.xmpp.server.SimpleComponentRegistry; import org.apache.vysper.xmpp.server.TestSessionContext; import org.apache.vysper.xmpp.stanza.Stanza; import org.apache.vysper.xmpp.stanza.StanzaBuilder; @@ -44,8 +47,6 @@ import org.apache.vysper.xmpp.state.resourcebinding.ResourceRegistry; import junit.framework.Assert; import junit.framework.TestCase; -import static org.mockito.Mockito.mock; - /** */ public class DeliveringInteralInboundStanzaRelayTestCase extends TestCase { @@ -73,18 +74,22 @@ public class DeliveringInteralInboundStanzaRelayTestCase extends TestCase { ; // empty } } + + private Entity serverEntity; @Override protected void setUp() throws Exception { super.setUp(); accountVerification = new AccountVerificationMock(); - stanzaRelay = new DeliveringInternalInboundStanzaRelay(EntityImpl.parse("vysper.org"), resourceRegistry, - accountVerification, null); + serverEntity = EntityImpl.parse("vysper.org"); + stanzaRelay = new DeliveringInternalInboundStanzaRelay(serverEntity, resourceRegistry, + new SimpleComponentRegistry(serverEntity), accountVerification, null); } public void testSimpleRelay() throws EntityFormatException, XMLSemanticError, DeliveryException { - DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(null, mock(StanzaRelay.class)); + DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(serverEntity, + mock(StanzaRelay.class)); stanzaRelay.setServerRuntimeContext(serverRuntimeContext); stanzaRelay.setStanzaRelay(stanzaRelay); @@ -123,7 +128,8 @@ public class DeliveringInteralInboundStanzaRelayTestCase extends TestCase { public void testRelayToTwoRecepients_DeliverToALL() throws EntityFormatException, XMLSemanticError, DeliveryException, BindException { - DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(null, mock(StanzaRelay.class)); + DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(serverEntity, + mock(StanzaRelay.class)); // !! DeliverMessageToHighestPriorityResourcesOnly = FALSE serverRuntimeContext.getServerFeatures().setDeliverMessageToHighestPriorityResourcesOnly(false); @@ -157,7 +163,8 @@ public class DeliveringInteralInboundStanzaRelayTestCase extends TestCase { public void testRelayToTwoRecepients_DeliverToHIGHEST() throws EntityFormatException, XMLSemanticError, DeliveryException, BindException { - DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(null, mock(StanzaRelay.class)); + DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(serverEntity, + mock(StanzaRelay.class)); // !! DeliverMessageToHighestPriorityResourcesOnly = TRUE serverRuntimeContext.getServerFeatures().setDeliverMessageToHighestPriorityResourcesOnly(true); @@ -216,7 +223,8 @@ public class DeliveringInteralInboundStanzaRelayTestCase extends TestCase { public void testSequentialDeliveryOneThread() throws DeliveryException, XMLSemanticError, EntityFormatException { - DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(null, mock(StanzaRelay.class)); + DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(serverEntity, + mock(StanzaRelay.class)); stanzaRelay.setServerRuntimeContext(serverRuntimeContext); stanzaRelay.setStanzaRelay(stanzaRelay); @@ -239,7 +247,8 @@ public class DeliveringInteralInboundStanzaRelayTestCase extends TestCase { public void testSequentialDeliveryManyThreads() throws DeliveryException, XMLSemanticError, EntityFormatException { - DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(null, mock(StanzaRelay.class)); + DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(serverEntity, + mock(StanzaRelay.class)); stanzaRelay.setServerRuntimeContext(serverRuntimeContext); stanzaRelay.setStanzaRelay(stanzaRelay); diff --git a/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java b/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java index 7e7beea..8a005e5 100644 --- a/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java +++ b/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/DiscoInfoIQHandlerTestCase.java @@ -22,8 +22,6 @@ package org.apache.vysper.xmpp.modules.servicediscovery.handler; import java.util.Arrays; import java.util.List; -import junit.framework.Assert; - import org.apache.vysper.StanzaAssert; import org.apache.vysper.xmpp.addressing.Entity; import org.apache.vysper.xmpp.addressing.EntityImpl; @@ -40,7 +38,6 @@ import org.apache.vysper.xmpp.protocol.ResponseStanzaContainerImpl; import org.apache.vysper.xmpp.protocol.StanzaBroker; import org.apache.vysper.xmpp.server.ServerRuntimeContext; import org.apache.vysper.xmpp.server.SessionContext; -import org.apache.vysper.xmpp.server.components.ComponentStanzaProcessor; import org.apache.vysper.xmpp.stanza.IQStanza; import org.apache.vysper.xmpp.stanza.IQStanzaType; import org.apache.vysper.xmpp.stanza.Stanza; @@ -52,31 +49,42 @@ import org.junit.Before; import org.junit.Test; import org.mockito.Mockito; +import junit.framework.Assert; + /** */ public class DiscoInfoIQHandlerTestCase extends Mockito { private static final Entity FROM = EntityImpl.parseUnchecked("f...@vysper.org"); + private static final Entity SERVER = EntityImpl.parseUnchecked("vysper.org"); + private static final Entity COMPONENT = EntityImpl.parseUnchecked("comp.vysper.org"); + private static final Entity USER = EntityImpl.parseUnchecked("u...@vysper.org"); + private static final Entity USER_WITH_RESOURCE = EntityImpl.parseUnchecked("u...@vysper.org/res1"); - + private ServerRuntimeContext serverRuntimeContext = mock(ServerRuntimeContext.class); + private SessionContext sessionContext = mock(SessionContext.class); + private ServiceCollector serviceCollector = mock(ServiceCollector.class); + private StanzaBroker stanzaBroker = mock(StanzaBroker.class); + private StanzaWriter stanzaWriter = mock(StanzaWriter.class); private IQStanza stanza = (IQStanza) IQStanza.getWrapper(buildStanza()); - + private DiscoInfoIQHandler handler = new DiscoInfoIQHandler(); - - private ComponentStanzaProcessor componentStanzaProcessor = mock(ComponentStanzaProcessor.class); + private Feature feature = new Feature("foo"); + private Identity identity = new Identity("bar", "fez"); + private List<InfoElement> infoElements = Arrays.asList(feature, identity); - + private Stanza buildStanza() { return buildStanza("iq", NamespaceURIs.JABBER_CLIENT, "query", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO); } @@ -84,15 +92,12 @@ public class DiscoInfoIQHandlerTestCase extends Mockito { private Stanza buildStanza(String name, String namespaceUri) { return buildStanza(name, namespaceUri, "query", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO); } - + private Stanza buildStanza(String name, String namespaceUri, String innerName, String innerNamespaceUri) { - return new StanzaBuilder(name, namespaceUri) - .addAttribute("type", "get") - .addAttribute("id", "1") - .startInnerElement(innerName, innerNamespaceUri) - .build(); + return new StanzaBuilder(name, namespaceUri).addAttribute("type", "get").addAttribute("id", "1") + .startInnerElement(innerName, innerNamespaceUri).build(); } - + @Test public void nameMustBeIq() { Assert.assertEquals("iq", handler.getName()); @@ -127,10 +132,11 @@ public class DiscoInfoIQHandlerTestCase extends Mockito { public void verifyInvalidInnerNamespace() { Assert.assertFalse(handler.verify(buildStanza("iq", NamespaceURIs.JABBER_CLIENT, "query", "dummy"))); } - + @Test public void verifyInvalidInnerName() { - Assert.assertFalse(handler.verify(buildStanza("iq", NamespaceURIs.JABBER_CLIENT, "dummy", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO))); + Assert.assertFalse(handler.verify( + buildStanza("iq", NamespaceURIs.JABBER_CLIENT, "dummy", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO))); } @Test @@ -138,7 +144,7 @@ public class DiscoInfoIQHandlerTestCase extends Mockito { Stanza stanza = new StanzaBuilder("iq", NamespaceURIs.JABBER_CLIENT).build(); Assert.assertFalse(handler.verify(stanza)); } - + @Test public void verifyValidStanza() { Assert.assertTrue(handler.verify(stanza)); @@ -148,12 +154,13 @@ public class DiscoInfoIQHandlerTestCase extends Mockito { public void sessionIsRequired() { Assert.assertTrue(handler.isSessionRequired()); } - + @Before public void before() { - when(serverRuntimeContext.getServerRuntimeContextService(ServiceDiscoveryRequestListenerRegistry.SERVICE_DISCOVERY_REQUEST_LISTENER_REGISTRY)) - .thenReturn(serviceCollector); - + when(serverRuntimeContext.getServerRuntimeContextService( + ServiceDiscoveryRequestListenerRegistry.SERVICE_DISCOVERY_REQUEST_LISTENER_REGISTRY)) + .thenReturn(serviceCollector); + when(serverRuntimeContext.getServerEntity()).thenReturn(SERVER); when(sessionContext.getResponseWriter()).thenReturn(stanzaWriter); } @@ -161,9 +168,9 @@ public class DiscoInfoIQHandlerTestCase extends Mockito { @Test public void handleGetToServer() throws Exception { IQStanza stanza = createRequest(SERVER); - + when(serviceCollector.processServerInfoRequest(any(InfoRequest.class))).thenReturn(infoElements); - + List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); StanzaAssert.assertEquals(createExpectedResponse(SERVER), response); @@ -172,67 +179,69 @@ public class DiscoInfoIQHandlerTestCase extends Mockito { @Test public void handleGetToExistingComponent() throws Exception { IQStanza stanza = createRequest(COMPONENT); - - when(serverRuntimeContext.getComponentStanzaProcessor(COMPONENT)).thenReturn(componentStanzaProcessor); - - when(serviceCollector.processComponentInfoRequest(any(InfoRequest.class), eq(stanzaBroker))).thenReturn(infoElements); + + when(serverRuntimeContext.hasComponentStanzaProcessor(COMPONENT)).thenReturn(true); + + when(serviceCollector.processComponentInfoRequest(any(InfoRequest.class), eq(stanzaBroker))) + .thenReturn(infoElements); List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + StanzaAssert.assertEquals(createExpectedResponse(COMPONENT), response); } @Test public void handleGetToUser() throws Exception { IQStanza stanza = createRequest(USER); - + when(serviceCollector.processInfoRequest(any(InfoRequest.class))).thenReturn(infoElements); List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + StanzaAssert.assertEquals(createExpectedResponse(USER), response); } @Test public void handleGetToUserWithResource() throws Exception { when(sessionContext.getInitiatingEntity()).thenReturn(FROM); - + IQStanza stanza = createRequest(USER_WITH_RESOURCE); - + List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Assert.assertNull(response); - + verify(stanzaBroker).write(eq(USER_WITH_RESOURCE), eq(stanza), any(DeliveryFailureStrategy.class)); } - + @Test public void handleGetToUserWithResourceInbound() throws Exception { when(sessionContext.getInitiatingEntity()).thenReturn(USER); - + IQStanza stanza = createRequest(USER_WITH_RESOURCE); - + List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Assert.assertNull(response); - + verify(stanzaWriter).write(stanza); } - + @Test public void handleGetToNonExistingComponent() throws Exception { IQStanza stanza = createRequest(COMPONENT); - - when(serverRuntimeContext.getComponentStanzaProcessor(COMPONENT)).thenReturn(null); - when(serviceCollector.processComponentInfoRequest(any(InfoRequest.class), eq(stanzaBroker))).thenReturn(infoElements); - + + when(serverRuntimeContext.hasComponentStanzaProcessor(COMPONENT)).thenReturn(false); + when(serviceCollector.processComponentInfoRequest(any(InfoRequest.class), eq(stanzaBroker))) + .thenReturn(infoElements); + List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Stanza expected = createErrorResponse(COMPONENT, "item-not-found"); StanzaAssert.assertEquals(expected, response); @@ -241,125 +250,118 @@ public class DiscoInfoIQHandlerTestCase extends Mockito { @Test public void handleGetNoServiceCollector() throws Exception { IQStanza stanza = createRequest(SERVER); - - when(serverRuntimeContext.getServerRuntimeContextService(ServiceDiscoveryRequestListenerRegistry.SERVICE_DISCOVERY_REQUEST_LISTENER_REGISTRY)) - .thenReturn(null); - + + when(serverRuntimeContext.getServerRuntimeContextService( + ServiceDiscoveryRequestListenerRegistry.SERVICE_DISCOVERY_REQUEST_LISTENER_REGISTRY)).thenReturn(null); + List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Stanza expected = createErrorResponse(SERVER, "internal-server-error"); - + StanzaAssert.assertEquals(expected, response); } - + @Test public void handleGetToServerWithException() throws Exception { IQStanza stanza = createRequest(SERVER); - - when(serviceCollector.processServerInfoRequest(any(InfoRequest.class))).thenThrow(new ServiceDiscoveryRequestException(StanzaErrorCondition.INTERNAL_SERVER_ERROR)); - + + when(serviceCollector.processServerInfoRequest(any(InfoRequest.class))) + .thenThrow(new ServiceDiscoveryRequestException(StanzaErrorCondition.INTERNAL_SERVER_ERROR)); + List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Stanza expected = createErrorResponse(SERVER, "internal-server-error"); - + StanzaAssert.assertEquals(expected, response); } - + @Test public void handleGetToComponentWithException() throws Exception { IQStanza stanza = createRequest(COMPONENT); - - when(serverRuntimeContext.getComponentStanzaProcessor(COMPONENT)).thenReturn(componentStanzaProcessor); - when(serviceCollector.processComponentInfoRequest(any(InfoRequest.class), eq(stanzaBroker))).thenThrow(new ServiceDiscoveryRequestException(StanzaErrorCondition.INTERNAL_SERVER_ERROR)); - + + when(serverRuntimeContext.hasComponentStanzaProcessor(COMPONENT)).thenReturn(true); + when(serviceCollector.processComponentInfoRequest(any(InfoRequest.class), eq(stanzaBroker))) + .thenThrow(new ServiceDiscoveryRequestException(StanzaErrorCondition.INTERNAL_SERVER_ERROR)); + List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Stanza expected = createErrorResponse(COMPONENT, "internal-server-error"); - + StanzaAssert.assertEquals(expected, response); } - + @Test public void handleGetToUserWithException() throws Exception { IQStanza stanza = createRequest(USER); - - when(serviceCollector.processInfoRequest(any(InfoRequest.class))).thenThrow(new ServiceDiscoveryRequestException(StanzaErrorCondition.INTERNAL_SERVER_ERROR)); - + + when(serviceCollector.processInfoRequest(any(InfoRequest.class))) + .thenThrow(new ServiceDiscoveryRequestException(StanzaErrorCondition.INTERNAL_SERVER_ERROR)); + List<Stanza> responses = handler.handleGet(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Stanza expected = createErrorResponse(SERVER, "internal-server-error"); - + StanzaAssert.assertEquals(expected, response); } - + @Test public void handleResultToUser() throws Exception { when(sessionContext.getInitiatingEntity()).thenReturn(FROM); - + IQStanza stanza = createRequest(USER, IQStanzaType.RESULT); List<Stanza> responses = handler.handleResult(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Assert.assertNull(response); - + verify(stanzaBroker).write(eq(USER), eq(stanza), any(DeliveryFailureStrategy.class)); } - + @Test public void handleResultToUserInbound() throws Exception { when(sessionContext.getInitiatingEntity()).thenReturn(USER); - + IQStanza stanza = createRequest(USER, IQStanzaType.RESULT); List<Stanza> responses = handler.handleResult(stanza, serverRuntimeContext, sessionContext, stanzaBroker); Stanza response = new ResponseStanzaContainerImpl(responses).getUniqueResponseStanza(); - + Assert.assertNull(response); - + verify(stanzaWriter).write(stanza); } - + private Stanza createErrorResponse(Entity from, String error) { Stanza expected = StanzaBuilder.createIQStanza(from, FROM, IQStanzaType.ERROR, "id1") - .startInnerElement("query", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO) - .addAttribute("node", "n") - .endInnerElement() - .startInnerElement("error", NamespaceURIs.JABBER_CLIENT) - .addAttribute("type", "cancel") - .startInnerElement(error, NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS) - .build(); + .startInnerElement("query", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO).addAttribute("node", "n") + .endInnerElement().startInnerElement("error", NamespaceURIs.JABBER_CLIENT) + .addAttribute("type", "cancel") + .startInnerElement(error, NamespaceURIs.URN_IETF_PARAMS_XML_NS_XMPP_STANZAS).build(); return expected; } - + private IQStanza createRequest(Entity to) { return createRequest(to, IQStanzaType.GET); } - + private IQStanza createRequest(Entity to, IQStanzaType type) { IQStanza stanza = (IQStanza) XMPPCoreStanza.getWrapper(StanzaBuilder.createIQStanza(FROM, to, type, "id1") - .startInnerElement("query", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO) - .addAttribute("node", "n") + .startInnerElement("query", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO).addAttribute("node", "n") .build()); return stanza; } private Stanza createExpectedResponse(Entity from) { Stanza expected = StanzaBuilder.createIQStanza(from, FROM, IQStanzaType.RESULT, "id1") - .startInnerElement("query", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO) - .addAttribute("node", "n") - .startInnerElement("feature", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO) - .addAttribute("var", "foo") - .endInnerElement() - .startInnerElement("identity", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO) - .addAttribute("category", "bar") - .addAttribute("type", "fez") - .endInnerElement() - .build(); + .startInnerElement("query", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO).addAttribute("node", "n") + .startInnerElement("feature", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO).addAttribute("var", "foo") + .endInnerElement().startInnerElement("identity", NamespaceURIs.XEP0030_SERVICE_DISCOVERY_INFO) + .addAttribute("category", "bar").addAttribute("type", "fez").endInnerElement().build(); return expected; } } diff --git a/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/ExtendedDiscoInfoTestCase.java b/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/ExtendedDiscoInfoTestCase.java index cb3c96c..0a41b4d 100644 --- a/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/ExtendedDiscoInfoTestCase.java +++ b/server/core/src/test/java/org/apache/vysper/xmpp/modules/servicediscovery/handler/ExtendedDiscoInfoTestCase.java @@ -78,8 +78,7 @@ public class ExtendedDiscoInfoTestCase extends TestCase { } }); - DefaultServerRuntimeContext runtimeContext = new DefaultServerRuntimeContext(EntityImpl.parse("vysper.org"), - mock(StanzaRelay.class)); + DefaultServerRuntimeContext runtimeContext = new DefaultServerRuntimeContext(EntityImpl.parse("vysper.org"), mock(StanzaRelay.class)); runtimeContext.registerServerRuntimeContextService(serviceCollector); DiscoInfoIQHandler infoIQHandler = new DiscoInfoIQHandler(); diff --git a/server/core/src/test/java/org/apache/vysper/xmpp/protocol/ProtocolWorkerStateAwarenessTestCase.java b/server/core/src/test/java/org/apache/vysper/xmpp/protocol/ProtocolWorkerStateAwarenessTestCase.java index 15c4c0f..f31cf4e 100644 --- a/server/core/src/test/java/org/apache/vysper/xmpp/protocol/ProtocolWorkerStateAwarenessTestCase.java +++ b/server/core/src/test/java/org/apache/vysper/xmpp/protocol/ProtocolWorkerStateAwarenessTestCase.java @@ -49,8 +49,7 @@ public class ProtocolWorkerStateAwarenessTestCase extends TestCase { Entity serverEnitity = new EntityImpl(null, "vysper-server.org", null); StanzaReceiverRelay receiverRelay = new StanzaReceiverRelay(); protocolWorker = new ProtocolWorker(receiverRelay); - DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(serverEnitity, - receiverRelay); + DefaultServerRuntimeContext serverRuntimeContext = new DefaultServerRuntimeContext(serverEnitity, receiverRelay); receiverRelay.setServerRuntimeContext(serverRuntimeContext); serverRuntimeContext.addDictionary(new BaseStreamStanzaDictionary()); sessionStateHolder = new SessionStateHolder(); diff --git a/server/core/src/test/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContextEventListenerTest.java b/server/core/src/test/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContextEventListenerTest.java index 374830f..fe767c0 100644 --- a/server/core/src/test/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContextEventListenerTest.java +++ b/server/core/src/test/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContextEventListenerTest.java @@ -24,6 +24,7 @@ import java.util.Optional; import org.apache.vysper.event.EventListenerDictionary; import org.apache.vysper.event.EventListenerMock; import org.apache.vysper.event.SimpleEventListenerDictionary; +import org.apache.vysper.xmpp.addressing.Entity; import org.apache.vysper.xmpp.delivery.StanzaRelay; import org.apache.vysper.xmpp.modules.DefaultModule; import org.junit.Before; @@ -46,7 +47,7 @@ public class DefaultServerRuntimeContextEventListenerTest { EventListenerDictionary listenerDictionary = SimpleEventListenerDictionary.builder() .register(Event.class, eventListener).build(); - tested = new DefaultServerRuntimeContext(null, mock(StanzaRelay.class)); + tested = new DefaultServerRuntimeContext(mock(Entity.class), mock(StanzaRelay.class)); tested.addModule(new MyModule(listenerDictionary)); }