Repository: aries-rsa Updated Branches: refs/heads/master 495a0e939 -> 965444751
[ARIES-1527] Make eventadmin optional Project: http://git-wip-us.apache.org/repos/asf/aries-rsa/repo Commit: http://git-wip-us.apache.org/repos/asf/aries-rsa/commit/96544475 Tree: http://git-wip-us.apache.org/repos/asf/aries-rsa/tree/96544475 Diff: http://git-wip-us.apache.org/repos/asf/aries-rsa/diff/96544475 Branch: refs/heads/master Commit: 965444751bec438b3220e1ae0ffbbd7d45ae6610 Parents: 495a0e9 Author: Guillaume Nodet <[email protected]> Authored: Tue Apr 12 14:48:10 2016 +0200 Committer: Christian Schneider <[email protected]> Committed: Tue Apr 12 15:49:39 2016 +0200 ---------------------------------------------------------------------- eapub/Readme.md | 3 + eapub/bnd.bnd | 2 + eapub/pom.xml | 26 +++ .../org/apache/aries/rsa/eapub/Activator.java | 39 ++++ .../aries/rsa/eapub/EventAdminHelper.java | 153 ++++++++++++++ .../aries/rsa/eapub/EventAdminHelperTest.java | 197 +++++++++++++++++++ features/src/main/resources/features.xml | 7 +- pom.xml | 1 + .../apache/aries/rsa/core/EventAdminHelper.java | 151 -------------- .../apache/aries/rsa/core/EventProducer.java | 42 ++-- .../aries/rsa/core/EventProducerTest.java | 88 +++------ 11 files changed, 481 insertions(+), 228 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/eapub/Readme.md ---------------------------------------------------------------------- diff --git a/eapub/Readme.md b/eapub/Readme.md new file mode 100644 index 0000000..5fd3dbf --- /dev/null +++ b/eapub/Readme.md @@ -0,0 +1,3 @@ +# Remote Service Admin EventAdmin Publisher + +Is used to publish EventAdmin events for Remote Service Admin events notifications. http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/eapub/bnd.bnd ---------------------------------------------------------------------- diff --git a/eapub/bnd.bnd b/eapub/bnd.bnd new file mode 100644 index 0000000..94d281a --- /dev/null +++ b/eapub/bnd.bnd @@ -0,0 +1,2 @@ +Bundle-Activator: org.apache.aries.rsa.eapub.Activator +Private-Package: org.apache.aries.rsa.eapub http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/eapub/pom.xml ---------------------------------------------------------------------- diff --git a/eapub/pom.xml b/eapub/pom.xml new file mode 100644 index 0000000..e6a1c9b --- /dev/null +++ b/eapub/pom.xml @@ -0,0 +1,26 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <parent> + <groupId>org.apache.aries.rsa</groupId> + <artifactId>org.apache.aries.rsa.parent</artifactId> + <version>1.9-SNAPSHOT</version> + <relativePath>../parent/pom.xml</relativePath> + </parent> + <artifactId>org.apache.aries.rsa.eapub</artifactId> + <packaging>bundle</packaging> + <name>Aries Remote Service Event Admin Publisher</name> + <description>The Remote Service Event Admin Publisher</description> + + <properties> + <topDirectoryLocation>..</topDirectoryLocation> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.aries.rsa</groupId> + <artifactId>org.apache.aries.rsa.spi</artifactId> + <scope>provided</scope> + </dependency> + </dependencies> + +</project> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/eapub/src/main/java/org/apache/aries/rsa/eapub/Activator.java ---------------------------------------------------------------------- diff --git a/eapub/src/main/java/org/apache/aries/rsa/eapub/Activator.java b/eapub/src/main/java/org/apache/aries/rsa/eapub/Activator.java new file mode 100644 index 0000000..8bf4cee --- /dev/null +++ b/eapub/src/main/java/org/apache/aries/rsa/eapub/Activator.java @@ -0,0 +1,39 @@ +/** + * 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.aries.rsa.eapub; + +import org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener; + +public class Activator implements BundleActivator { + + private ServiceRegistration<RemoteServiceAdminListener> registration; + + public void start(BundleContext bundlecontext) throws Exception { + registration = bundlecontext.registerService( + RemoteServiceAdminListener.class, new EventAdminHelper(bundlecontext), null); + } + + public void stop(BundleContext context) throws Exception { + registration.unregister(); + } + +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/eapub/src/main/java/org/apache/aries/rsa/eapub/EventAdminHelper.java ---------------------------------------------------------------------- diff --git a/eapub/src/main/java/org/apache/aries/rsa/eapub/EventAdminHelper.java b/eapub/src/main/java/org/apache/aries/rsa/eapub/EventAdminHelper.java new file mode 100644 index 0000000..d560a8f --- /dev/null +++ b/eapub/src/main/java/org/apache/aries/rsa/eapub/EventAdminHelper.java @@ -0,0 +1,153 @@ +/** + * 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.aries.rsa.eapub; + +import java.util.HashMap; +import java.util.Map; + +import org.osgi.framework.BundleContext; +import org.osgi.framework.InvalidSyntaxException; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.Version; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class EventAdminHelper implements RemoteServiceAdminListener { + + private static final Logger LOG = LoggerFactory.getLogger(EventAdminHelper.class); + + private BundleContext bctx; + + public EventAdminHelper(BundleContext bc) { + bctx = bc; + } + + private Event createEvent(Map<String, Object> props, String type) { + String topic = "org/osgi/service/remoteserviceadmin/" + type; + props.put("bundle", bctx.getBundle()); + props.put("bundle.id", bctx.getBundle().getBundleId()); + props.put("bundle.symbolicname", bctx.getBundle().getSymbolicName()); + + String version = (String)bctx.getBundle().getHeaders().get("Bundle-Version"); + Version v = version != null ? new Version(version) : Version.emptyVersion; + setIfNotNull(props, "bundle.version", v); + + return new Event(topic, props); + } + + @Override + public void remoteAdminEvent(RemoteServiceAdminEvent rsae) { + String topic = remoteServiceAdminEventTypeToString(rsae.getType()); + + Map<String, Object> props = new HashMap<String, Object>(); + setIfNotNull(props, "cause", rsae.getException()); + + EndpointDescription endpoint = null; + if (rsae.getImportReference() != null) { + endpoint = rsae.getImportReference().getImportedEndpoint(); + setIfNotNull(props, "import.registration", endpoint); + } else if (rsae.getExportReference() != null) { + endpoint = rsae.getExportReference().getExportedEndpoint(); + setIfNotNull(props, "export.registration", endpoint); + } + + if (endpoint != null) { + setIfNotNull(props, "service.remote.id", endpoint.getServiceId()); + setIfNotNull(props, "service.remote.uuid", endpoint.getFrameworkUUID()); + setIfNotNull(props, "service.remote.uri", endpoint.getId()); + setIfNotNull(props, "objectClass", endpoint.getInterfaces().toArray()); + setIfNotNull(props, "service.imported.configs", endpoint.getConfigurationTypes()); + } + props.put("timestamp", System.currentTimeMillis()); + props.put("event", rsae); + + Event event = createEvent(props, topic); + notifyEventAdmins(topic, event); + } + + @SuppressWarnings({ + "rawtypes", "unchecked" + }) + private void notifyEventAdmins(String topic, Event event) { + ServiceReference[] refs = null; + try { + refs = bctx.getAllServiceReferences(EventAdmin.class.getName(), null); + } catch (InvalidSyntaxException e) { + LOG.error("Failed to get EventAdmin: " + e.getMessage(), e); + } + + if (refs != null) { + LOG.debug("Publishing event to {} EventAdmins; Topic:[{}]", refs.length, topic); + for (ServiceReference serviceReference : refs) { + EventAdmin eventAdmin = (EventAdmin) bctx.getService(serviceReference); + try { + eventAdmin.postEvent(event); + } finally { + if (eventAdmin != null) { + bctx.ungetService(serviceReference); + } + } + } + } + } + + private <K, V> void setIfNotNull(Map<K, V> map, K key, V val) { + if (val != null) { + map.put(key, val); + } + } + + private static String remoteServiceAdminEventTypeToString(int type) { + String retval; + switch (type) { + case RemoteServiceAdminEvent.EXPORT_ERROR: + retval = "EXPORT_ERROR"; + break; + case RemoteServiceAdminEvent.EXPORT_REGISTRATION: + retval = "EXPORT_REGISTRATION"; + break; + case RemoteServiceAdminEvent.EXPORT_UNREGISTRATION: + retval = "EXPORT_UNREGISTRATION"; + break; + case RemoteServiceAdminEvent.EXPORT_WARNING: + retval = "EXPORT_WARNING"; + break; + case RemoteServiceAdminEvent.IMPORT_ERROR: + retval = "IMPORT_ERROR"; + break; + case RemoteServiceAdminEvent.IMPORT_REGISTRATION: + retval = "IMPORT_REGISTRATION"; + break; + case RemoteServiceAdminEvent.IMPORT_UNREGISTRATION: + retval = "IMPORT_UNREGISTRATION"; + break; + case RemoteServiceAdminEvent.IMPORT_WARNING: + retval = "IMPORT_WARNING"; + break; + default: + retval = "UNKNOWN_EVENT"; + } + return retval; + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/eapub/src/test/java/org/apache/aries/rsa/eapub/EventAdminHelperTest.java ---------------------------------------------------------------------- diff --git a/eapub/src/test/java/org/apache/aries/rsa/eapub/EventAdminHelperTest.java b/eapub/src/test/java/org/apache/aries/rsa/eapub/EventAdminHelperTest.java new file mode 100644 index 0000000..e08a05f --- /dev/null +++ b/eapub/src/test/java/org/apache/aries/rsa/eapub/EventAdminHelperTest.java @@ -0,0 +1,197 @@ +/** + * 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.aries.rsa.eapub; + +import java.util.Arrays; +import java.util.Dictionary; +import java.util.Hashtable; +import java.util.List; +import java.util.UUID; + +import org.easymock.EasyMock; +import org.easymock.IAnswer; +import org.junit.Assert; +import org.junit.Test; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.Version; +import org.osgi.service.event.Event; +import org.osgi.service.event.EventAdmin; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ExportReference; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; + +@SuppressWarnings({"rawtypes", "unchecked"}) +public class EventAdminHelperTest { + + @Test + public void testPublishNotification() throws Exception { + final EndpointDescription epd = EasyMock.createNiceMock(EndpointDescription.class); + EasyMock.expect(epd.getServiceId()).andReturn(Long.MAX_VALUE).anyTimes(); + final String uuid = UUID.randomUUID().toString(); + EasyMock.expect(epd.getFrameworkUUID()).andReturn(uuid).anyTimes(); + EasyMock.expect(epd.getId()).andReturn("foo://bar").anyTimes(); + final List<String> interfaces = Arrays.asList("org.foo.Bar", "org.boo.Far"); + EasyMock.expect(epd.getInterfaces()).andReturn(interfaces).anyTimes(); + EasyMock.expect(epd.getConfigurationTypes()).andReturn(Arrays.asList("org.apache.cxf.ws")).anyTimes(); + EasyMock.replay(epd); + final ServiceReference sref = EasyMock.createNiceMock(ServiceReference.class); + EasyMock.replay(sref); + final ExportReference er = EasyMock.createNiceMock(ExportReference.class); + EasyMock.expect(er.getExportedEndpoint()).andReturn(epd).anyTimes(); + EasyMock.expect(er.getExportedService()).andReturn(sref).anyTimes(); + EasyMock.replay(er); + + final Bundle bundle = EasyMock.createNiceMock(Bundle.class); + EasyMock.expect(bundle.getBundleId()).andReturn(42L).anyTimes(); + EasyMock.expect(bundle.getSymbolicName()).andReturn("test.bundle").anyTimes(); + Dictionary<String, String> headers = new Hashtable<String, String>(); + headers.put("Bundle-Version", "1.2.3.test"); + EasyMock.expect(bundle.getHeaders()).andReturn(headers).anyTimes(); + EasyMock.replay(bundle); + + EventAdmin ea = EasyMock.createNiceMock(EventAdmin.class); + ea.postEvent((Event) EasyMock.anyObject()); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + Event event = (Event) EasyMock.getCurrentArguments()[0]; + + Assert.assertEquals("org/osgi/service/remoteserviceadmin/EXPORT_REGISTRATION", event.getTopic()); + Assert.assertSame(bundle, event.getProperty("bundle")); + Assert.assertEquals(42L, event.getProperty("bundle.id")); + Assert.assertEquals("test.bundle", event.getProperty("bundle.symbolicname")); + Assert.assertEquals(new Version(1, 2, 3, "test"), event.getProperty("bundle.version")); + Assert.assertNull(event.getProperty("cause")); + Assert.assertEquals(epd, event.getProperty("export.registration")); + + Assert.assertEquals(Long.MAX_VALUE, event.getProperty("service.remote.id")); + Assert.assertEquals(uuid, event.getProperty("service.remote.uuid")); + Assert.assertEquals("foo://bar", event.getProperty("service.remote.uri")); + Assert.assertTrue(Arrays.equals(interfaces.toArray(new String[] {}), + (String[]) event.getProperty("objectClass"))); + + Assert.assertNotNull(event.getProperty("timestamp")); + + RemoteServiceAdminEvent rsae = (RemoteServiceAdminEvent) event.getProperty("event"); + Assert.assertNull(rsae.getException()); + Assert.assertEquals(RemoteServiceAdminEvent.EXPORT_REGISTRATION, rsae.getType()); + Assert.assertSame(bundle, rsae.getSource()); + ExportReference er = rsae.getExportReference(); + Assert.assertSame(epd, er.getExportedEndpoint()); + Assert.assertSame(sref, er.getExportedService()); + + return null; + } + }); + EasyMock.replay(ea); + + ServiceReference eaSref = EasyMock.createNiceMock(ServiceReference.class); + EasyMock.replay(eaSref); + + BundleContext bc = EasyMock.createNiceMock(BundleContext.class); + EasyMock.expect(bc.getBundle()).andReturn(bundle).anyTimes(); + EasyMock.expect(bc.getAllServiceReferences(EventAdmin.class.getName(), null)) + .andReturn(new ServiceReference[] {eaSref}).anyTimes(); + EasyMock.expect(bc.getService(eaSref)).andReturn(ea).anyTimes(); + EasyMock.replay(bc); + + RemoteServiceAdminEvent event = new RemoteServiceAdminEvent( + RemoteServiceAdminEvent.EXPORT_REGISTRATION, + bundle, + er, + null + ); + new EventAdminHelper(bc).remoteAdminEvent(event); + EasyMock.verify(epd, sref, er, ea, eaSref, bc); + } + + @Test + public void testPublishErrorNotification() throws Exception { + final EndpointDescription epd = EasyMock.createNiceMock(EndpointDescription.class); + EasyMock.expect(epd.getInterfaces()).andReturn(Arrays.asList("org.foo.Bar")).anyTimes(); + EasyMock.replay(epd); + final ServiceReference sref = EasyMock.createNiceMock(ServiceReference.class); + EasyMock.replay(sref); + final ExportReference er = EasyMock.createNiceMock(ExportReference.class); + EasyMock.expect(er.getExportedEndpoint()).andReturn(epd).anyTimes(); + EasyMock.expect(er.getExportedService()).andReturn(sref).anyTimes(); + EasyMock.replay(er); + + final Bundle bundle = EasyMock.createNiceMock(Bundle.class); + EasyMock.expect(bundle.getBundleId()).andReturn(42L).anyTimes(); + EasyMock.expect(bundle.getSymbolicName()).andReturn("test.bundle").anyTimes(); + EasyMock.expect(bundle.getHeaders()).andReturn(new Hashtable<String, String>()).anyTimes(); + EasyMock.replay(bundle); + + final Exception exportException = new Exception(); + + EventAdmin ea = EasyMock.createNiceMock(EventAdmin.class); + ea.postEvent((Event) EasyMock.anyObject()); + EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { + @Override + public Object answer() throws Throwable { + Event event = (Event) EasyMock.getCurrentArguments()[0]; + + Assert.assertEquals("org/osgi/service/remoteserviceadmin/EXPORT_ERROR", event.getTopic()); + Assert.assertSame(bundle, event.getProperty("bundle")); + Assert.assertEquals(42L, event.getProperty("bundle.id")); + Assert.assertEquals("test.bundle", event.getProperty("bundle.symbolicname")); + Assert.assertEquals(new Version("0"), event.getProperty("bundle.version")); + Assert.assertSame(exportException, event.getProperty("cause")); + Assert.assertEquals(epd, event.getProperty("export.registration")); + Assert.assertTrue(Arrays.equals(new String[] {"org.foo.Bar"}, + (String[]) event.getProperty("objectClass"))); + + RemoteServiceAdminEvent rsae = (RemoteServiceAdminEvent) event.getProperty("event"); + Assert.assertSame(exportException, rsae.getException()); + Assert.assertEquals(RemoteServiceAdminEvent.EXPORT_ERROR, rsae.getType()); + Assert.assertSame(bundle, rsae.getSource()); + ExportReference er = rsae.getExportReference(); + Assert.assertSame(epd, er.getExportedEndpoint()); + Assert.assertSame(sref, er.getExportedService()); + + return null; + } + }); + EasyMock.replay(ea); + + ServiceReference eaSref = EasyMock.createNiceMock(ServiceReference.class); + EasyMock.replay(eaSref); + + BundleContext bc = EasyMock.createNiceMock(BundleContext.class); + + EasyMock.expect(bc.getBundle()).andReturn(bundle).anyTimes(); + EasyMock.expect(bc.getAllServiceReferences(EventAdmin.class.getName(), null)) + .andReturn(new ServiceReference[] {eaSref}).anyTimes(); + EasyMock.expect(bc.getService(eaSref)).andReturn(ea).anyTimes(); + EasyMock.replay(bc); + + + RemoteServiceAdminEvent event = new RemoteServiceAdminEvent( + RemoteServiceAdminEvent.EXPORT_ERROR, + bundle, + er, + exportException + ); + new EventAdminHelper(bc).remoteAdminEvent(event); + EasyMock.verify(epd, sref, er, ea, eaSref, bc); + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/features/src/main/resources/features.xml ---------------------------------------------------------------------- diff --git a/features/src/main/resources/features.xml b/features/src/main/resources/features.xml index bf55d79..be79a3b 100644 --- a/features/src/main/resources/features.xml +++ b/features/src/main/resources/features.xml @@ -1,11 +1,14 @@ <?xml version="1.0" encoding="UTF-8"?> -<features xmlns="http://karaf.apache.org/xmlns/features/v1.0.0" name="aries-rsa-${project.version}"> +<features xmlns="http://karaf.apache.org/xmlns/features/v1.2.0" name="aries-rsa-${project.version}"> <feature name="aries-rsa-core" version="${project.version}"> - <feature>eventadmin</feature> <bundle>mvn:org.apache.aries.rsa/org.apache.aries.rsa.spi/${project.version}</bundle> <bundle>mvn:org.apache.aries.rsa/org.apache.aries.rsa.core/${project.version}</bundle> <bundle>mvn:org.apache.aries.rsa/org.apache.aries.rsa.topology-manager/${project.version}</bundle> + <conditional> + <condition>eventadmin</condition> + <bundle>mvn:org.apache.aries.rsa/org.apache.aries.rsa.eapub/${project.version}</bundle> + </conditional> </feature> <feature name="aries-rsa-provider-tcp" version="${project.version}"> http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/pom.xml ---------------------------------------------------------------------- diff --git a/pom.xml b/pom.xml index 6886ea3..c519e37 100644 --- a/pom.xml +++ b/pom.xml @@ -78,6 +78,7 @@ <module>parent</module> <module>spi</module> <module>rsa</module> + <module>eapub</module> <module>topology-manager</module> <module>provider</module> <module>discovery</module> http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/rsa/src/main/java/org/apache/aries/rsa/core/EventAdminHelper.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/EventAdminHelper.java b/rsa/src/main/java/org/apache/aries/rsa/core/EventAdminHelper.java deleted file mode 100644 index e59c0ef..0000000 --- a/rsa/src/main/java/org/apache/aries/rsa/core/EventAdminHelper.java +++ /dev/null @@ -1,151 +0,0 @@ -/** - * 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.aries.rsa.core; - -import java.util.HashMap; -import java.util.Map; - -import org.osgi.framework.BundleContext; -import org.osgi.framework.InvalidSyntaxException; -import org.osgi.framework.ServiceReference; -import org.osgi.framework.Version; -import org.osgi.service.event.Event; -import org.osgi.service.event.EventAdmin; -import org.osgi.service.remoteserviceadmin.EndpointDescription; -import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EventAdminHelper { - - private static final Logger LOG = LoggerFactory.getLogger(EventAdminHelper.class); - - private BundleContext bctx; - - public EventAdminHelper(BundleContext bc) { - bctx = bc; - } - - private Event createEvent(Map<String, Object> props, String type) { - String topic = "org/osgi/service/remoteserviceadmin/" + type; - props.put("bundle", bctx.getBundle()); - props.put("bundle.id", bctx.getBundle().getBundleId()); - props.put("bundle.symbolicname", bctx.getBundle().getSymbolicName()); - - String version = (String)bctx.getBundle().getHeaders().get("Bundle-Version"); - Version v = version != null ? new Version(version) : Version.emptyVersion; - setIfNotNull(props, "bundle.version", v); - - return new Event(topic, props); - } - - public void notifyEventAdmin(RemoteServiceAdminEvent rsae) { - String topic = remoteServiceAdminEventTypeToString(rsae.getType()); - - Map<String, Object> props = new HashMap<String, Object>(); - setIfNotNull(props, "cause", rsae.getException()); - - EndpointDescription endpoint = null; - if (rsae.getImportReference() != null) { - endpoint = ((ImportRegistrationImpl)rsae.getImportReference()).getImportedEndpointAlways(); - setIfNotNull(props, "import.registration", endpoint); - } else if (rsae.getExportReference() != null) { - endpoint = rsae.getExportReference().getExportedEndpoint(); - setIfNotNull(props, "export.registration", endpoint); - } - - if (endpoint != null) { - setIfNotNull(props, "service.remote.id", endpoint.getServiceId()); - setIfNotNull(props, "service.remote.uuid", endpoint.getFrameworkUUID()); - setIfNotNull(props, "service.remote.uri", endpoint.getId()); - setIfNotNull(props, "objectClass", endpoint.getInterfaces().toArray()); - setIfNotNull(props, "service.imported.configs", endpoint.getConfigurationTypes()); - } - props.put("timestamp", System.currentTimeMillis()); - props.put("event", rsae); - - Event event = createEvent(props, topic); - notifyEventAdmins(topic, event); - } - - @SuppressWarnings({ - "rawtypes", "unchecked" - }) - private void notifyEventAdmins(String topic, Event event) { - ServiceReference[] refs = null; - try { - refs = bctx.getAllServiceReferences(EventAdmin.class.getName(), null); - } catch (InvalidSyntaxException e) { - LOG.error("Failed to get EventAdmin: " + e.getMessage(), e); - } - - if (refs != null) { - LOG.debug("Publishing event to {} EventAdmins; Topic:[{}]", refs.length, topic); - for (ServiceReference serviceReference : refs) { - EventAdmin eventAdmin = (EventAdmin) bctx.getService(serviceReference); - try { - eventAdmin.postEvent(event); - } finally { - if (eventAdmin != null) { - bctx.ungetService(serviceReference); - } - } - } - } - } - - private <K, V> void setIfNotNull(Map<K, V> map, K key, V val) { - if (val != null) { - map.put(key, val); - } - } - - private static String remoteServiceAdminEventTypeToString(int type) { - String retval; - switch (type) { - case RemoteServiceAdminEvent.EXPORT_ERROR: - retval = "EXPORT_ERROR"; - break; - case RemoteServiceAdminEvent.EXPORT_REGISTRATION: - retval = "EXPORT_REGISTRATION"; - break; - case RemoteServiceAdminEvent.EXPORT_UNREGISTRATION: - retval = "EXPORT_UNREGISTRATION"; - break; - case RemoteServiceAdminEvent.EXPORT_WARNING: - retval = "EXPORT_WARNING"; - break; - case RemoteServiceAdminEvent.IMPORT_ERROR: - retval = "IMPORT_ERROR"; - break; - case RemoteServiceAdminEvent.IMPORT_REGISTRATION: - retval = "IMPORT_REGISTRATION"; - break; - case RemoteServiceAdminEvent.IMPORT_UNREGISTRATION: - retval = "IMPORT_UNREGISTRATION"; - break; - case RemoteServiceAdminEvent.IMPORT_WARNING: - retval = "IMPORT_WARNING"; - break; - default: - retval = "UNKNOWN_EVENT"; - } - return retval; - } -} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/rsa/src/main/java/org/apache/aries/rsa/core/EventProducer.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/EventProducer.java b/rsa/src/main/java/org/apache/aries/rsa/core/EventProducer.java index 4098201..0d9453b 100644 --- a/rsa/src/main/java/org/apache/aries/rsa/core/EventProducer.java +++ b/rsa/src/main/java/org/apache/aries/rsa/core/EventProducer.java @@ -24,7 +24,9 @@ import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.InvalidSyntaxException; import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.ExportReference; import org.osgi.service.remoteserviceadmin.ExportRegistration; +import org.osgi.service.remoteserviceadmin.ImportReference; import org.osgi.service.remoteserviceadmin.ImportRegistration; import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener; @@ -35,11 +37,9 @@ public class EventProducer { private static final Logger LOG = LoggerFactory.getLogger(EventProducer.class); private final BundleContext bctx; - private final EventAdminHelper eaHelper; public EventProducer(BundleContext bc) { bctx = bc; - eaHelper = new EventAdminHelper(bctx); } protected void publishNotification(List<ExportRegistration> erl) { @@ -49,35 +49,41 @@ public class EventProducer { } protected void publishNotification(ExportRegistration er) { - int type = er.getException() == null - ? RemoteServiceAdminEvent.EXPORT_REGISTRATION - : RemoteServiceAdminEvent.EXPORT_ERROR; - notify(type, null, er); + if (er.getException() == null) { + notify(RemoteServiceAdminEvent.EXPORT_REGISTRATION, er.getExportReference(), null); + } else { + notify(RemoteServiceAdminEvent.EXPORT_ERROR, (ExportReference) null, er.getException()); + } } protected void publishNotification(ImportRegistration ir) { - int type = ir.getException() == null - ? RemoteServiceAdminEvent.IMPORT_REGISTRATION - : RemoteServiceAdminEvent.IMPORT_ERROR; - notify(type, ir, null); + if (ir.getException() == null) { + notify(RemoteServiceAdminEvent.IMPORT_REGISTRATION, ir.getImportReference(), null); + } else { + notify(RemoteServiceAdminEvent.IMPORT_ERROR, (ImportReference) null, ir.getException()); + } } public void notifyRemoval(ExportRegistration er) { - notify(RemoteServiceAdminEvent.EXPORT_UNREGISTRATION, null, er); + notify(RemoteServiceAdminEvent.EXPORT_UNREGISTRATION, er.getExportReference(), null); } public void notifyRemoval(ImportRegistration ir) { - notify(RemoteServiceAdminEvent.IMPORT_UNREGISTRATION, ir, null); + notify(RemoteServiceAdminEvent.IMPORT_UNREGISTRATION, ir.getImportReference(), null); } - // only one of ir or er must be set, and the other must be null - private void notify(int type, ImportRegistration ir, ExportRegistration er) { + private void notify(int type, ExportReference er, Throwable ex) { + try { + RemoteServiceAdminEvent event = new RemoteServiceAdminEvent(type, bctx.getBundle(), er, ex); + notifyListeners(event); + } catch (IllegalStateException ise) { + LOG.debug("can't send notifications since bundle context is no longer valid"); + } + } + private void notify(int type, ImportReference ir, Throwable ex) { try { - RemoteServiceAdminEvent event = ir != null - ? new RemoteServiceAdminEvent(type, bctx.getBundle(), ir.getImportReference(), ir.getException()) - : new RemoteServiceAdminEvent(type, bctx.getBundle(), er.getExportReference(), er.getException()); + RemoteServiceAdminEvent event = new RemoteServiceAdminEvent(type, bctx.getBundle(), ir, ex); notifyListeners(event); - eaHelper.notifyEventAdmin(event); } catch (IllegalStateException ise) { LOG.debug("can't send notifications since bundle context is no longer valid"); } http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/96544475/rsa/src/test/java/org/apache/aries/rsa/core/EventProducerTest.java ---------------------------------------------------------------------- diff --git a/rsa/src/test/java/org/apache/aries/rsa/core/EventProducerTest.java b/rsa/src/test/java/org/apache/aries/rsa/core/EventProducerTest.java index 2714a65..8b00534 100644 --- a/rsa/src/test/java/org/apache/aries/rsa/core/EventProducerTest.java +++ b/rsa/src/test/java/org/apache/aries/rsa/core/EventProducerTest.java @@ -32,13 +32,11 @@ import org.junit.Test; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; -import org.osgi.framework.Version; -import org.osgi.service.event.Event; -import org.osgi.service.event.EventAdmin; import org.osgi.service.remoteserviceadmin.EndpointDescription; import org.osgi.service.remoteserviceadmin.ExportReference; import org.osgi.service.remoteserviceadmin.ExportRegistration; import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener; @SuppressWarnings({"rawtypes", "unchecked"}) public class EventProducerTest { @@ -46,8 +44,8 @@ public class EventProducerTest { @Test public void testPublishNotification() throws Exception { - RemoteServiceAdminCore remoteServiceAdminCore = EasyMock.createNiceMock(RemoteServiceAdminCore.class); - EasyMock.replay(remoteServiceAdminCore); + RemoteServiceAdminCore rsaCore = EasyMock.createNiceMock(RemoteServiceAdminCore.class); + EasyMock.replay(rsaCore); final EndpointDescription epd = EasyMock.createNiceMock(EndpointDescription.class); EasyMock.expect(epd.getServiceId()).andReturn(Long.MAX_VALUE).anyTimes(); @@ -69,30 +67,12 @@ public class EventProducerTest { EasyMock.expect(bundle.getHeaders()).andReturn(headers).anyTimes(); EasyMock.replay(bundle); - EventAdmin ea = EasyMock.createNiceMock(EventAdmin.class); - ea.postEvent((Event) EasyMock.anyObject()); + RemoteServiceAdminListener rsal = EasyMock.createNiceMock(RemoteServiceAdminListener.class); + rsal.remoteAdminEvent((RemoteServiceAdminEvent) EasyMock.anyObject()); EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { @Override public Object answer() throws Throwable { - Event event = (Event) EasyMock.getCurrentArguments()[0]; - - Assert.assertEquals("org/osgi/service/remoteserviceadmin/EXPORT_REGISTRATION", event.getTopic()); - Assert.assertSame(bundle, event.getProperty("bundle")); - Assert.assertEquals(42L, event.getProperty("bundle.id")); - Assert.assertEquals("test.bundle", event.getProperty("bundle.symbolicname")); - Assert.assertEquals(new Version(1, 2, 3, "test"), event.getProperty("bundle.version")); - Assert.assertNull(event.getProperty("cause")); - Assert.assertEquals(epd, event.getProperty("export.registration")); - - Assert.assertEquals(Long.MAX_VALUE, event.getProperty("service.remote.id")); - Assert.assertEquals(uuid, event.getProperty("service.remote.uuid")); - Assert.assertEquals("foo://bar", event.getProperty("service.remote.uri")); - Assert.assertTrue(Arrays.equals(interfaces.toArray(new String[] {}), - (String[]) event.getProperty("objectClass"))); - - Assert.assertNotNull(event.getProperty("timestamp")); - - RemoteServiceAdminEvent rsae = (RemoteServiceAdminEvent) event.getProperty("event"); + RemoteServiceAdminEvent rsae = (RemoteServiceAdminEvent) EasyMock.getCurrentArguments()[0]; Assert.assertNull(rsae.getException()); Assert.assertEquals(RemoteServiceAdminEvent.EXPORT_REGISTRATION, rsae.getType()); Assert.assertSame(bundle, rsae.getSource()); @@ -103,24 +83,27 @@ public class EventProducerTest { return null; } }); - EasyMock.replay(ea); + EasyMock.replay(rsal); - ServiceReference eaSref = EasyMock.createNiceMock(ServiceReference.class); - EasyMock.replay(eaSref); + ServiceReference rsalSref = EasyMock.createNiceMock(ServiceReference.class); + EasyMock.expect(rsalSref.getBundle()).andReturn(bundle).anyTimes(); + EasyMock.replay(rsalSref); BundleContext bc = EasyMock.createNiceMock(BundleContext.class); EasyMock.expect(bc.getBundle()).andReturn(bundle).anyTimes(); - EasyMock.expect(bc.getAllServiceReferences(EventAdmin.class.getName(), null)) - .andReturn(new ServiceReference[] {eaSref}).anyTimes(); - EasyMock.expect(bc.getService(eaSref)).andReturn(ea).anyTimes(); + EasyMock.expect(bc.getServiceReferences(RemoteServiceAdminListener.class.getName(), null)) + .andReturn(new ServiceReference[] {rsalSref}).anyTimes(); + EasyMock.expect(bc.getService(rsalSref)).andReturn(rsal).anyTimes(); Endpoint endpoint = EasyMock.mock(Endpoint.class); EasyMock.expect(endpoint.description()).andReturn(epd); EasyMock.replay(endpoint); EasyMock.replay(bc); EventProducer eventProducer = new EventProducer(bc); - ExportRegistrationImpl ereg = new ExportRegistrationImpl(sref, endpoint, remoteServiceAdminCore); + ExportRegistrationImpl ereg = new ExportRegistrationImpl(sref, endpoint, rsaCore); eventProducer.publishNotification(ereg); + + EasyMock.verify(rsaCore, sref, bundle, rsal, rsalSref, bc); } @Test @@ -142,48 +125,39 @@ public class EventProducerTest { final Exception exportException = new Exception(); - EventAdmin ea = EasyMock.createNiceMock(EventAdmin.class); - ea.postEvent((Event) EasyMock.anyObject()); + RemoteServiceAdminListener rsal = EasyMock.createNiceMock(RemoteServiceAdminListener.class); + rsal.remoteAdminEvent((RemoteServiceAdminEvent) EasyMock.anyObject()); EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() { @Override public Object answer() throws Throwable { - Event event = (Event) EasyMock.getCurrentArguments()[0]; - - Assert.assertEquals("org/osgi/service/remoteserviceadmin/EXPORT_ERROR", event.getTopic()); - Assert.assertSame(bundle, event.getProperty("bundle")); - Assert.assertEquals(42L, event.getProperty("bundle.id")); - Assert.assertEquals("test.bundle", event.getProperty("bundle.symbolicname")); - Assert.assertEquals(new Version("0"), event.getProperty("bundle.version")); - Assert.assertSame(exportException, event.getProperty("cause")); - Assert.assertEquals(endpoint, event.getProperty("export.registration")); - Assert.assertTrue(Arrays.equals(new String[] {"org.foo.Bar"}, - (String[]) event.getProperty("objectClass"))); - - RemoteServiceAdminEvent rsae = (RemoteServiceAdminEvent) event.getProperty("event"); + RemoteServiceAdminEvent rsae = (RemoteServiceAdminEvent) EasyMock.getCurrentArguments()[0]; Assert.assertSame(exportException, rsae.getException()); Assert.assertEquals(RemoteServiceAdminEvent.EXPORT_ERROR, rsae.getType()); Assert.assertSame(bundle, rsae.getSource()); - ExportReference er = rsae.getExportReference(); - Assert.assertSame(endpoint, er.getExportedEndpoint()); - Assert.assertSame(sref, er.getExportedService()); + Assert.assertNull(rsae.getImportReference()); + Assert.assertNull(rsae.getExportReference()); return null; } }); - EasyMock.replay(ea); + EasyMock.replay(rsal); - ServiceReference eaSref = EasyMock.createNiceMock(ServiceReference.class); - EasyMock.replay(eaSref); + ServiceReference rsalSref = EasyMock.createNiceMock(ServiceReference.class); + EasyMock.expect(rsalSref.getBundle()).andReturn(bundle).anyTimes(); + EasyMock.replay(rsalSref); BundleContext bc = EasyMock.createNiceMock(BundleContext.class); + EasyMock.expect(bc.getBundle()).andReturn(bundle).anyTimes(); - EasyMock.expect(bc.getAllServiceReferences(EventAdmin.class.getName(), null)) - .andReturn(new ServiceReference[] {eaSref}).anyTimes(); - EasyMock.expect(bc.getService(eaSref)).andReturn(ea).anyTimes(); + EasyMock.expect(bc.getServiceReferences(RemoteServiceAdminListener.class.getName(), null)) + .andReturn(new ServiceReference[] {rsalSref}).anyTimes(); + EasyMock.expect(bc.getService(rsalSref)).andReturn(rsal).anyTimes(); EasyMock.replay(bc); EventProducer eventProducer = new EventProducer(bc); ExportRegistrationImpl ereg = new ExportRegistrationImpl(rsaCore, exportException); eventProducer.publishNotification(Arrays.<ExportRegistration>asList(ereg)); + + EasyMock.verify(rsaCore, sref, bundle, rsal, rsalSref, bc); } }
