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 f85334c Add an event bus (#10) f85334c is described below commit f85334c2f3652bf92fa137904d8a3e7650575bc3 Author: Réda Housni Alaoui <rala...@apache.org> AuthorDate: Sat Aug 17 10:26:42 2019 +0200 Add an event bus (#10) --- .../java/org/apache/vysper/event/EventBus.java | 32 +++++ .../org/apache/vysper/event/EventListener.java | 34 +++++ .../vysper/event/EventListenerDictionary.java | 34 +++++ .../org/apache/vysper/event/SimpleEventBus.java | 61 +++++++++ .../event/SimpleEventListenerDictionary.java | 70 +++++++++++ .../apache/vysper/xmpp/modules/DefaultModule.java | 7 ++ .../org/apache/vysper/xmpp/modules/Module.java | 12 +- .../xmpp/server/DefaultServerRuntimeContext.java | 20 ++- .../vysper/xmpp/server/ServerRuntimeContext.java | 3 + .../org/apache/vysper/event/EventListenerMock.java | 57 +++++++++ .../apache/vysper/event/SimpleEventBusTest.java | 140 +++++++++++++++++++++ ...faultServerRuntimeContextEventListenerTest.java | 84 +++++++++++++ 12 files changed, 549 insertions(+), 5 deletions(-) diff --git a/server/core/src/main/java/org/apache/vysper/event/EventBus.java b/server/core/src/main/java/org/apache/vysper/event/EventBus.java new file mode 100644 index 0000000..003e695 --- /dev/null +++ b/server/core/src/main/java/org/apache/vysper/event/EventBus.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.event; + +/** + * @author Réda Housni Alaoui + */ +public interface EventBus { + + /** + * Publishes an event. + */ + <T> EventBus publish(Class<T> eventType, T event); + +} diff --git a/server/core/src/main/java/org/apache/vysper/event/EventListener.java b/server/core/src/main/java/org/apache/vysper/event/EventListener.java new file mode 100644 index 0000000..14927f0 --- /dev/null +++ b/server/core/src/main/java/org/apache/vysper/event/EventListener.java @@ -0,0 +1,34 @@ +/* + * 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.event; + +/** + * @author Réda Housni Alaoui + */ +public interface EventListener<T> { + + /** + * Called when an event is to be handled by this listener. Any exception thrown + * by this method will be swiftly trapped. This method cannot and should not try + * to stop/alter the workflow that produced the event. + */ + void onEvent(T event); + +} diff --git a/server/core/src/main/java/org/apache/vysper/event/EventListenerDictionary.java b/server/core/src/main/java/org/apache/vysper/event/EventListenerDictionary.java new file mode 100644 index 0000000..32e6602 --- /dev/null +++ b/server/core/src/main/java/org/apache/vysper/event/EventListenerDictionary.java @@ -0,0 +1,34 @@ +/* + * 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.event; + +import java.util.Set; + +/** + * @author Réda Housni Alaoui + */ +public interface EventListenerDictionary { + + /** + * @return The listeners registered for the provided event type. + */ + Set<EventListener<?>> get(Class<?> eventType); + +} diff --git a/server/core/src/main/java/org/apache/vysper/event/SimpleEventBus.java b/server/core/src/main/java/org/apache/vysper/event/SimpleEventBus.java new file mode 100644 index 0000000..74ed21c --- /dev/null +++ b/server/core/src/main/java/org/apache/vysper/event/SimpleEventBus.java @@ -0,0 +1,61 @@ +/* + * 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.event; + +import java.util.Collection; +import java.util.LinkedHashSet; +import java.util.Set; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Réda Housni Alaoui + */ +public class SimpleEventBus implements EventBus { + + private static final Logger LOG = LoggerFactory.getLogger(SimpleEventBus.class); + + private final Set<EventListenerDictionary> listenerDictionaries = new LinkedHashSet<>(); + + public SimpleEventBus addDictionary(EventListenerDictionary dictionary) { + listenerDictionaries.add(dictionary); + return this; + } + + @Override + public <T> EventBus publish(Class<T> eventType, T event) { + listenerDictionaries.stream().map(eventListenerDictionary -> eventListenerDictionary.get(eventType)) + .flatMap(Collection::stream).distinct().forEach(listener -> fireEvent(event, listener)); + return this; + } + + @SuppressWarnings("unchecked") + private <T> void fireEvent(T event, EventListener<?> listener) { + LOG.trace("Firing event {} on listener {}", event, listener); + try { + ((EventListener<T>) listener).onEvent(event); + LOG.trace("Fired event {} on listener {}", event, listener); + } catch (Exception e) { + LOG.error(e.getMessage(), e); + } + } + +} diff --git a/server/core/src/main/java/org/apache/vysper/event/SimpleEventListenerDictionary.java b/server/core/src/main/java/org/apache/vysper/event/SimpleEventListenerDictionary.java new file mode 100644 index 0000000..3402b60 --- /dev/null +++ b/server/core/src/main/java/org/apache/vysper/event/SimpleEventListenerDictionary.java @@ -0,0 +1,70 @@ +/* + * 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.event; + +import static java.util.Optional.ofNullable; + +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Set; + +/** + * @author Réda Housni Alaoui + */ +public class SimpleEventListenerDictionary implements EventListenerDictionary { + + private final Map<Class<?>, Set<EventListener<?>>> listenersByEventType; + + private SimpleEventListenerDictionary(Map<Class<?>, Set<EventListener<?>>> listenersByEventType) { + this.listenersByEventType = new HashMap<>(listenersByEventType); + } + + @Override + public Set<EventListener<?>> get(Class<?> eventType) { + return ofNullable(listenersByEventType.get(eventType)).orElse(Collections.emptySet()); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private final Map<Class<?>, Set<EventListener<?>>> listenersByEventType = new HashMap<>(); + + private Builder() { + } + + /** + * Register the provided listener to the provided event type. Since the listener + * reference will never be released, be aware of possible memory leak. + */ + public <T> Builder register(Class<T> eventType, EventListener<T> listener) { + listenersByEventType.computeIfAbsent(eventType, type -> new LinkedHashSet<>()).add(listener); + return this; + } + + public SimpleEventListenerDictionary build() { + return new SimpleEventListenerDictionary(listenersByEventType); + } + } + +} diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/modules/DefaultModule.java b/server/core/src/main/java/org/apache/vysper/xmpp/modules/DefaultModule.java index 05f6457..e8c2e4b 100644 --- a/server/core/src/main/java/org/apache/vysper/xmpp/modules/DefaultModule.java +++ b/server/core/src/main/java/org/apache/vysper/xmpp/modules/DefaultModule.java @@ -21,7 +21,9 @@ package org.apache.vysper.xmpp.modules; import java.util.ArrayList; import java.util.List; +import java.util.Optional; +import org.apache.vysper.event.EventListenerDictionary; import org.apache.vysper.xmpp.protocol.HandlerDictionary; import org.apache.vysper.xmpp.server.ServerRuntimeContext; @@ -46,6 +48,11 @@ public abstract class DefaultModule implements Module { // empty default implementation } + @Override + public Optional<EventListenerDictionary> getEventListenerDictionary() { + return Optional.empty(); + } + public List<ServerRuntimeContextService> getServerServices() { List<ServerRuntimeContextService> serviceList = new ArrayList<ServerRuntimeContextService>(); addServerServices(serviceList); diff --git a/server/core/src/main/java/org/apache/vysper/xmpp/modules/Module.java b/server/core/src/main/java/org/apache/vysper/xmpp/modules/Module.java index e1fee0f..2a9ef08 100644 --- a/server/core/src/main/java/org/apache/vysper/xmpp/modules/Module.java +++ b/server/core/src/main/java/org/apache/vysper/xmpp/modules/Module.java @@ -20,7 +20,9 @@ package org.apache.vysper.xmpp.modules; import java.util.List; +import java.util.Optional; +import org.apache.vysper.event.EventListenerDictionary; import org.apache.vysper.xmpp.protocol.HandlerDictionary; import org.apache.vysper.xmpp.server.ServerRuntimeContext; import org.apache.vysper.xmpp.server.XMPPServer; @@ -33,6 +35,8 @@ import org.apache.vysper.xmpp.server.XMPPServer; * <li>doing initializations, for example adding request listeners to the ServiceDiscoveryRequestListenerRegistry</li> * <li>adding dictionaries with new stanza handlers getting registered with the server which then get called as * matching stanzas arrive</li> + * <li>adding dictionaries with new event listeners getting registered with the server which then get called as + * matching events are published</li> * </ul> * * TODO: think about returning the supported XEPs @@ -41,6 +45,7 @@ import org.apache.vysper.xmpp.server.XMPPServer; * @see org.apache.vysper.xmpp.modules.DefaultDiscoAwareModule recommended for modules responding to service disco requests * @see org.apache.vysper.xmpp.modules.ServerRuntimeContextService * @see org.apache.vysper.xmpp.protocol.HandlerDictionary + * @see EventListenerDictionary * * @author The Apache MINA Project (d...@mina.apache.org) */ @@ -51,11 +56,16 @@ public interface Module { String getVersion(); /** - * all dictionaries to be added to the server + * all stanza handler dictionaries to be added to the server */ List<HandlerDictionary> getHandlerDictionaries(); /** + * @return The event listener dictionary to be added to the server + */ + Optional<EventListenerDictionary> getEventListenerDictionary(); + + /** * all objects to be added to the server runtime context */ List<ServerRuntimeContextService> getServerServices(); 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 fde5102..439a6c3 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 @@ -28,6 +28,8 @@ import java.util.Map; import javax.net.ssl.SSLContext; +import org.apache.vysper.event.EventBus; +import org.apache.vysper.event.SimpleEventBus; import org.apache.vysper.storage.OpenStorageProviderRegistry; import org.apache.vysper.storage.StorageProvider; import org.apache.vysper.storage.StorageProviderRegistry; @@ -63,7 +65,7 @@ import org.slf4j.LoggerFactory; */ public class DefaultServerRuntimeContext implements ServerRuntimeContext, ModuleRegistry { - final Logger logger = LoggerFactory.getLogger(DefaultServerRuntimeContext.class); + private final Logger logger = LoggerFactory.getLogger(DefaultServerRuntimeContext.class); // basic internal data structures and configuration... @@ -124,7 +126,7 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module /** * collection of all other services, which are mostly add-ons to the minimal setup */ - final private Map<String, ServerRuntimeContextService> serverRuntimeContextServiceMap = new HashMap<String, ServerRuntimeContextService>(); + private final Map<String, ServerRuntimeContextService> serverRuntimeContextServiceMap = new HashMap<String, ServerRuntimeContextService>(); private List<Module> modules = new ArrayList<Module>(); @@ -132,12 +134,15 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module * 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 SimpleEventBus eventBus; public DefaultServerRuntimeContext(Entity serverEntity, StanzaRelay stanzaRelay) { this.serverEntity = serverEntity; this.stanzaRelay = stanzaRelay; this.resourceRegistry = new DefaultResourceRegistry(); this.stanzaHandlerLookup = new StanzaHandlerLookup(this); + this.eventBus = new SimpleEventBus(); } public DefaultServerRuntimeContext(Entity serverEntity, StanzaRelay stanzaRelay, @@ -304,7 +309,7 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module * 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 - * @param modules + * @param module */ public void addModule(Module module) { addModuleInternal(module); @@ -337,6 +342,8 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module } + module.getEventListenerDictionary().ifPresent(eventBus::addDictionary); + if (module instanceof Component) { registerComponent((Component) module); } @@ -354,7 +361,12 @@ public class DefaultServerRuntimeContext implements ServerRuntimeContext, Module } return null; } - + + @Override + public EventBus getEventBus() { + return eventBus; + } + public void registerComponent(Component component) { componentMap.put(component.getSubdomain(), component); } 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 0972ab4..88ebbb3 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 @@ -24,6 +24,7 @@ import java.util.List; import javax.net.ssl.SSLContext; +import org.apache.vysper.event.EventBus; import org.apache.vysper.storage.StorageProvider; import org.apache.vysper.xmpp.addressing.Entity; import org.apache.vysper.xmpp.authentication.UserAuthentication; @@ -83,4 +84,6 @@ public interface ServerRuntimeContext { <T> T getModule(Class<T> clazz); void addModule(Module module); + + EventBus getEventBus(); } diff --git a/server/core/src/test/java/org/apache/vysper/event/EventListenerMock.java b/server/core/src/test/java/org/apache/vysper/event/EventListenerMock.java new file mode 100644 index 0000000..7fd2d9c --- /dev/null +++ b/server/core/src/test/java/org/apache/vysper/event/EventListenerMock.java @@ -0,0 +1,57 @@ +/* + * 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.event; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import junit.framework.Assert; + +/** + * @author Réda Housni Alaoui + */ +public class EventListenerMock<T> implements EventListener<T> { + + private final List<T> receivedEventsSequence = new ArrayList<>(); + + private boolean failOnReceivedEvent; + + public EventListenerMock<T> failOnReceivedEvent() { + failOnReceivedEvent = true; + return this; + } + + public void assertReceivedEventsSequence(T... events) { + Assert.assertEquals(Arrays.asList(events), receivedEventsSequence); + } + + public void assertNoEventReceived() { + Assert.assertTrue(receivedEventsSequence.isEmpty()); + } + + @Override + public void onEvent(T event) { + receivedEventsSequence.add(event); + if (failOnReceivedEvent) { + throw new RuntimeException("Failing as asked"); + } + } +} diff --git a/server/core/src/test/java/org/apache/vysper/event/SimpleEventBusTest.java b/server/core/src/test/java/org/apache/vysper/event/SimpleEventBusTest.java new file mode 100644 index 0000000..0c0f93d --- /dev/null +++ b/server/core/src/test/java/org/apache/vysper/event/SimpleEventBusTest.java @@ -0,0 +1,140 @@ +/* + * 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.event; + +import org.junit.Before; +import org.junit.Test; + +/** + * @author Réda Housni Alaoui + */ +public class SimpleEventBusTest { + + private EventListenerMock<FooEvent> fooListener; + + private EventListenerMock<BarEvent> barListener; + + private EventListenerMock<BazEvent> bazListener; + + private SimpleEventBus tested; + + @Before + public void before() { + tested = new SimpleEventBus(); + + fooListener = new EventListenerMock<>(); + barListener = new EventListenerMock<>(); + bazListener = new EventListenerMock<>(); + } + + @Test + public void publishEventGivenOneDictionary() { + tested.addDictionary(SimpleEventListenerDictionary.builder().register(FooEvent.class, fooListener) + .register(BarEvent.class, barListener).register(BazEvent.class, bazListener).build()); + + FooEvent fooEvent = new FooEvent(); + tested.publish(FooEvent.class, fooEvent); + BarEvent barEvent = new BarEvent(); + tested.publish(BarEvent.class, barEvent); + BazEvent bazEvent = new BazEvent(); + tested.publish(BazEvent.class, bazEvent); + + fooListener.assertReceivedEventsSequence(fooEvent); + barListener.assertReceivedEventsSequence(barEvent); + bazListener.assertReceivedEventsSequence(bazEvent); + } + + @Test + public void publishEventGivenTwoDictionaries() { + tested.addDictionary(SimpleEventListenerDictionary.builder().register(FooEvent.class, fooListener) + .register(BarEvent.class, barListener).build()) + .addDictionary(SimpleEventListenerDictionary.builder().register(BazEvent.class, bazListener).build()); + + FooEvent fooEvent = new FooEvent(); + tested.publish(FooEvent.class, fooEvent); + BarEvent barEvent = new BarEvent(); + tested.publish(BarEvent.class, barEvent); + BazEvent bazEvent = new BazEvent(); + tested.publish(BazEvent.class, bazEvent); + + fooListener.assertReceivedEventsSequence(fooEvent); + barListener.assertReceivedEventsSequence(barEvent); + bazListener.assertReceivedEventsSequence(bazEvent); + } + + @Test + public void publishEventGivenListenerRegisteredTwiceInOneDictionary() { + tested.addDictionary(SimpleEventListenerDictionary.builder().register(FooEvent.class, fooListener) + .register(FooEvent.class, fooListener).build()); + + FooEvent fooEvent = new FooEvent(); + tested.publish(FooEvent.class, fooEvent); + fooListener.assertReceivedEventsSequence(fooEvent); + } + + @Test + public void publishEventGivenListenerRegisteredTwiceInTwoDifferentDictionary() { + tested.addDictionary(SimpleEventListenerDictionary.builder().register(FooEvent.class, fooListener).build()) + .addDictionary(SimpleEventListenerDictionary.builder().register(FooEvent.class, fooListener).build()); + + FooEvent event = new FooEvent(); + tested.publish(FooEvent.class, event); + fooListener.assertReceivedEventsSequence(event); + } + + @Test + public void publishSubClassEvent() { + tested.addDictionary(SimpleEventListenerDictionary.builder().register(FooEvent.class, fooListener).build()); + + SubFooEvent event = new SubFooEvent(); + tested.publish(FooEvent.class, event); + fooListener.assertReceivedEventsSequence(event); + } + + @Test + public void publishOnTwoListenersGivenOneFailingListener() { + EventListenerMock<FooEvent> failingListener = new EventListenerMock<FooEvent>().failOnReceivedEvent(); + tested.addDictionary(SimpleEventListenerDictionary.builder().register(FooEvent.class, failingListener) + .register(FooEvent.class, fooListener).build()); + + FooEvent event = new FooEvent(); + tested.publish(FooEvent.class, event); + + failingListener.assertReceivedEventsSequence(event); + fooListener.assertReceivedEventsSequence(event); + } + + private static class FooEvent { + + } + + private static class BarEvent { + + } + + private static class BazEvent { + + } + + private static class SubFooEvent extends FooEvent { + + } + +} \ No newline at end of file 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 new file mode 100644 index 0000000..2e2f520 --- /dev/null +++ b/server/core/src/test/java/org/apache/vysper/xmpp/server/DefaultServerRuntimeContextEventListenerTest.java @@ -0,0 +1,84 @@ +/* + * 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 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.modules.DefaultModule; +import org.junit.Before; +import org.junit.Test; + +/** + * @author Réda Housni Alaoui + */ +public class DefaultServerRuntimeContextEventListenerTest { + + private EventListenerMock<Event> eventListener; + + private DefaultServerRuntimeContext tested; + + @Before + public void before() { + eventListener = new EventListenerMock<>(); + EventListenerDictionary listenerDictionary = SimpleEventListenerDictionary.builder() + .register(Event.class, eventListener).build(); + + tested = new DefaultServerRuntimeContext(null, null); + tested.addModule(new MyModule(listenerDictionary)); + } + + @Test + public void publishEventGivenRegisteredModule() { + Event event = new Event(); + tested.getEventBus().publish(Event.class, event); + eventListener.assertReceivedEventsSequence(event); + } + + private static class Event { + + } + + private static class MyModule extends DefaultModule { + + private final EventListenerDictionary eventListenerDictionary; + + private MyModule(EventListenerDictionary eventListenerDictionary) { + this.eventListenerDictionary = eventListenerDictionary; + } + + @Override + public String getName() { + return "MyModule"; + } + + @Override + public String getVersion() { + return "1.0"; + } + + @Override + public Optional<EventListenerDictionary> getEventListenerDictionary() { + return Optional.of(eventListenerDictionary); + } + } +} \ No newline at end of file