You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ro...@apache.org on 2017/11/07 10:19:04 UTC
[sling-org-apache-sling-testing-osgi-mock] 07/13: SLING-4719
osgi-mock: Add Mock EventAdmin implementation
This is an automated email from the ASF dual-hosted git repository.
rombert pushed a commit to annotated tag org.apache.sling.testing.osgi-mock-1.3.0
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-testing-osgi-mock.git
commit dd6302023421029a93e78b8f125de28dc72dd916
Author: Stefan Seifert <ss...@apache.org>
AuthorDate: Sun May 17 12:33:08 2015 +0000
SLING-4719 osgi-mock: Add Mock EventAdmin implementation
git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/testing/mocks/osgi-mock@1679849 13f79535-47bb-0310-9956-ffa450edef68
---
pom.xml | 8 +
.../sling/testing/mock/osgi/MockEventAdmin.java | 169 +++++++++++++++++++++
.../testing/mock/osgi/context/OsgiContextImpl.java | 10 +-
.../sling/testing/mock/osgi/package-info.java | 2 +-
.../testing/mock/osgi/MockEventAdminTest.java | 133 ++++++++++++++++
5 files changed, 320 insertions(+), 2 deletions(-)
diff --git a/pom.xml b/pom.xml
index 564ddc1..4d2ec30 100644
--- a/pom.xml
+++ b/pom.xml
@@ -64,6 +64,13 @@
</dependency>
<dependency>
+ <groupId>org.apache.sling</groupId>
+ <artifactId>org.apache.sling.commons.osgi</artifactId>
+ <version>2.2.0</version>
+ <scope>compile</scope>
+ </dependency>
+
+ <dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>15.0</version>
@@ -110,6 +117,7 @@
<groupId>org.apache.felix</groupId>
<artifactId>maven-scr-plugin</artifactId>
</plugin>
+
<plugin>
<groupId>org.apache.rat</groupId>
<artifactId>apache-rat-plugin</artifactId>
diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/MockEventAdmin.java b/src/main/java/org/apache/sling/testing/mock/osgi/MockEventAdmin.java
new file mode 100644
index 0000000..68d55ca
--- /dev/null
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/MockEventAdmin.java
@@ -0,0 +1,169 @@
+/*
+ * 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.sling.testing.mock.osgi;
+
+import java.util.Map;
+import java.util.TreeMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.commons.osgi.ServiceUtil;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Mock implementation of {@link EventAdmin}.
+ * From {@link EventConstants} currently only {@link EventConstants#EVENT_TOPIC} is supported.
+ */
+@Component(immediate = true)
+@Service(value = EventAdmin.class)
+public final class MockEventAdmin implements EventAdmin {
+
+ @Reference(name="eventHandler", referenceInterface=EventHandler.class,
+ cardinality=ReferenceCardinality.OPTIONAL_MULTIPLE, policy=ReferencePolicy.DYNAMIC)
+ private final Map<Object, EventHandlerItem> eventHandlers = new TreeMap<Object, EventHandlerItem>();
+
+ private ExecutorService asyncHandler = Executors.newCachedThreadPool();
+
+ private static final Logger log = LoggerFactory.getLogger(MockEventAdmin.class);
+
+ @Override
+ public void postEvent(final Event event) {
+ asyncHandler.execute(new Runnable() {
+ @Override
+ public void run() {
+ distributeEvent(event);
+ }
+ });
+ }
+
+ @Override
+ public void sendEvent(final Event event) {
+ distributeEvent(event);
+ }
+
+ private void distributeEvent(Event event) {
+ synchronized (eventHandlers) {
+ for (EventHandlerItem item : eventHandlers.values()) {
+ if (item.matches(event)) {
+ try {
+ item.getEventHandler().handleEvent(event);
+ }
+ catch (Throwable ex) {
+ log.error("Error handlihng event {} in {}", event, item.getEventHandler());
+ }
+ }
+ }
+ }
+ }
+
+ protected void bindEventHandler(EventHandler eventHandler, Map<String, Object> props) {
+ synchronized (eventHandlers) {
+ eventHandlers.put(ServiceUtil.getComparableForServiceRanking(props), new EventHandlerItem(eventHandler, props));
+ }
+ }
+
+ protected void unbindEventHandler(EventHandler eventHandler, Map<String, Object> props) {
+ synchronized (eventHandlers) {
+ eventHandlers.remove(ServiceUtil.getComparableForServiceRanking(props));
+ }
+ }
+
+ private static class EventHandlerItem {
+
+ private final EventHandler eventHandler;
+ private final Pattern[] topicPatterns;
+
+ private static final Pattern WILDCARD_PATTERN = Pattern.compile("[^*]+|(\\*)");
+
+ public EventHandlerItem(EventHandler eventHandler, Map<String, Object> props) {
+ this.eventHandler = eventHandler;
+ topicPatterns = generateTopicPatterns(props.get(EventConstants.EVENT_TOPIC));
+ }
+
+ public boolean matches(Event event) {
+ if (topicPatterns.length == 0) {
+ return true;
+ }
+ String topic = event.getTopic();
+ if (topic != null) {
+ for (Pattern topicPattern : topicPatterns) {
+ if (topicPattern.matcher(topic).matches()) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public EventHandler getEventHandler() {
+ return eventHandler;
+ }
+
+ private static Pattern[] generateTopicPatterns(Object topic) {
+ String[] topics;
+ if (topic == null) {
+ topics = new String[0];
+ }
+ else if (topic instanceof String) {
+ topics = new String[] { (String)topic };
+ }
+ else if (topic instanceof String[]) {
+ topics = (String[])topic;
+ }
+ else {
+ throw new IllegalArgumentException("Invalid topic: " + topic);
+ }
+ Pattern[] patterns = new Pattern[topics.length];
+ for (int i=0; i<topics.length; i++) {
+ patterns[i] = toWildcardPattern(topics[i]);
+ }
+ return patterns;
+ }
+
+ /**
+ * Converts a wildcard string with * to a regex pattern (from http://stackoverflow.com/questions/24337657/wildcard-matching-in-java)
+ * @param wildcard
+ * @return Regexp pattern
+ */
+ private static Pattern toWildcardPattern(String wildcard) {
+ Matcher matcher = WILDCARD_PATTERN.matcher(wildcard);
+ StringBuffer result = new StringBuffer();
+ while (matcher.find()) {
+ if(matcher.group(1) != null) matcher.appendReplacement(result, ".*");
+ else matcher.appendReplacement(result, "\\\\Q" + matcher.group(0) + "\\\\E");
+ }
+ matcher.appendTail(result);
+ return Pattern.compile(result.toString());
+ }
+
+ }
+
+}
diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/context/OsgiContextImpl.java b/src/main/java/org/apache/sling/testing/mock/osgi/context/OsgiContextImpl.java
index fb01663..27abf9f 100644
--- a/src/main/java/org/apache/sling/testing/mock/osgi/context/OsgiContextImpl.java
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/context/OsgiContextImpl.java
@@ -24,6 +24,7 @@ import java.util.Hashtable;
import java.util.Map;
import org.apache.commons.lang3.ArrayUtils;
+import org.apache.sling.testing.mock.osgi.MockEventAdmin;
import org.apache.sling.testing.mock.osgi.MockOsgi;
import org.osgi.framework.BundleContext;
import org.osgi.framework.InvalidSyntaxException;
@@ -45,7 +46,7 @@ public class OsgiContextImpl {
* Setup actions before test method execution
*/
protected void setUp() {
- // can be overridden by subclasses
+ registerDefaultServices();
}
/**
@@ -56,6 +57,13 @@ public class OsgiContextImpl {
}
/**
+ * Default services that should be available for every unit test
+ */
+ private void registerDefaultServices() {
+ registerInjectActivateService(new MockEventAdmin());
+ }
+
+ /**
* @return OSGi component context
*/
public final ComponentContext componentContext() {
diff --git a/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java b/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
index 6a6de3f..76826a4 100644
--- a/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
+++ b/src/main/java/org/apache/sling/testing/mock/osgi/package-info.java
@@ -19,5 +19,5 @@
/**
* Mock implementation of selected OSGi APIs.
*/
-@aQute.bnd.annotation.Version("2.0")
+@aQute.bnd.annotation.Version("2.1")
package org.apache.sling.testing.mock.osgi;
diff --git a/src/test/java/org/apache/sling/testing/mock/osgi/MockEventAdminTest.java b/src/test/java/org/apache/sling/testing/mock/osgi/MockEventAdminTest.java
new file mode 100644
index 0000000..fa3f675
--- /dev/null
+++ b/src/test/java/org/apache/sling/testing/mock/osgi/MockEventAdminTest.java
@@ -0,0 +1,133 @@
+/*
+ * 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.sling.testing.mock.osgi;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.sling.testing.mock.osgi.junit.OsgiContext;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.service.event.EventConstants;
+import org.osgi.service.event.EventHandler;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class MockEventAdminTest {
+
+ private static final String TOPIC_SAMPLE_1 = "sample/topic1";
+ private static final String TOPIC_SAMPLE_2 = "sample/topic2";
+ private static final String TOPIC_SAMPLE_ALL = "sample/*";
+ private static final String TOPIC_OTHER_3 = "other/topic3";
+
+ private static final Event EVENT_SAMPLE_1 = new Event(TOPIC_SAMPLE_1, null);
+ private static final Event EVENT_SAMPLE_2 = new Event(TOPIC_SAMPLE_2, null);
+ private static final Event EVENT_OTHER_3 = new Event(TOPIC_OTHER_3, null);
+
+ @Rule
+ public OsgiContext context = new OsgiContext();
+
+ private DummyEventHandler eventHandler1;
+ private DummyEventHandler eventHandler12;
+ private DummyEventHandler eventHandlerSampleAll;
+ private DummyEventHandler eventHandlerAll;
+
+ @Before
+ public void setUp() {
+ eventHandler1 = (DummyEventHandler)context.registerService(EventHandler.class, new DummyEventHandler(),
+ ImmutableMap.<String, Object>of(EventConstants.EVENT_TOPIC, TOPIC_SAMPLE_1));
+ eventHandler12 = (DummyEventHandler)context.registerService(EventHandler.class, new DummyEventHandler(),
+ ImmutableMap.<String, Object>of(EventConstants.EVENT_TOPIC, new String[] { TOPIC_SAMPLE_1, TOPIC_SAMPLE_2 }));
+ eventHandlerSampleAll = (DummyEventHandler)context.registerService(EventHandler.class, new DummyEventHandler(),
+ ImmutableMap.<String, Object>of(EventConstants.EVENT_TOPIC, TOPIC_SAMPLE_ALL));
+ eventHandlerAll = (DummyEventHandler)context.registerService(EventHandler.class, new DummyEventHandler());
+ }
+
+ @Test
+ public void testSendEvent_Sample1() {
+ EventAdmin eventAdmin = context.getService(EventAdmin.class);
+ eventAdmin.sendEvent(EVENT_SAMPLE_1);
+
+ assertEquals(ImmutableList.of(EVENT_SAMPLE_1), eventHandler1.getReceivedEvents());
+ assertEquals(ImmutableList.of(EVENT_SAMPLE_1), eventHandler12.getReceivedEvents());
+ assertEquals(ImmutableList.of(EVENT_SAMPLE_1), eventHandlerSampleAll.getReceivedEvents());
+ assertEquals(ImmutableList.of(EVENT_SAMPLE_1), eventHandlerAll.getReceivedEvents());
+ }
+
+ @Test
+ public void testSendEvent_Sample2() {
+ EventAdmin eventAdmin = context.getService(EventAdmin.class);
+ eventAdmin.sendEvent(EVENT_SAMPLE_2);
+
+ assertEquals(ImmutableList.of(), eventHandler1.getReceivedEvents());
+ assertEquals(ImmutableList.of(EVENT_SAMPLE_2), eventHandler12.getReceivedEvents());
+ assertEquals(ImmutableList.of(EVENT_SAMPLE_2), eventHandlerSampleAll.getReceivedEvents());
+ assertEquals(ImmutableList.of(EVENT_SAMPLE_2), eventHandlerAll.getReceivedEvents());
+ }
+
+ @Test
+ public void testSendEvent_Other3() {
+ EventAdmin eventAdmin = context.getService(EventAdmin.class);
+ eventAdmin.sendEvent(EVENT_OTHER_3);
+
+ assertEquals(ImmutableList.of(), eventHandler1.getReceivedEvents());
+ assertEquals(ImmutableList.of(), eventHandler12.getReceivedEvents());
+ assertEquals(ImmutableList.of(), eventHandlerSampleAll.getReceivedEvents());
+ assertEquals(ImmutableList.of(EVENT_OTHER_3), eventHandlerAll.getReceivedEvents());
+ }
+
+ @Test(timeout = 1000)
+ public void testPostEvents() {
+ EventAdmin eventAdmin = context.getService(EventAdmin.class);
+ eventAdmin.postEvent(EVENT_SAMPLE_2);
+ eventAdmin.postEvent(EVENT_OTHER_3);
+
+ // wait until result is as expected (with timeout)
+ boolean expectedResult = false;
+ while (!expectedResult) {
+ expectedResult = ObjectUtils.equals(ImmutableList.of(), eventHandler1.getReceivedEvents())
+ && ObjectUtils.equals(ImmutableList.of(EVENT_SAMPLE_2), eventHandler12.getReceivedEvents())
+ && ObjectUtils.equals(ImmutableList.of(EVENT_SAMPLE_2), eventHandlerSampleAll.getReceivedEvents())
+ && ObjectUtils.equals(ImmutableList.of(EVENT_SAMPLE_2, EVENT_OTHER_3), eventHandlerAll.getReceivedEvents());
+ }
+ }
+
+ private static class DummyEventHandler implements EventHandler {
+
+ private final List<Event> receivedEvents = new ArrayList<Event>();
+
+ @Override
+ public void handleEvent(Event event) {
+ receivedEvents.add(event);
+ }
+
+ public List<Event> getReceivedEvents() {
+ return ImmutableList.copyOf(receivedEvents);
+ }
+
+ }
+
+}
--
To stop receiving notification emails like this one, please contact
"commits@sling.apache.org" <co...@sling.apache.org>.