http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/discovery/zookeeper/src/main/java/org/apache/cxf/dosgi/discovery/zookeeper/util/Utils.java ---------------------------------------------------------------------- diff --git a/discovery/zookeeper/src/main/java/org/apache/cxf/dosgi/discovery/zookeeper/util/Utils.java b/discovery/zookeeper/src/main/java/org/apache/cxf/dosgi/discovery/zookeeper/util/Utils.java index 5fcb111..62f2268 100644 --- a/discovery/zookeeper/src/main/java/org/apache/cxf/dosgi/discovery/zookeeper/util/Utils.java +++ b/discovery/zookeeper/src/main/java/org/apache/cxf/dosgi/discovery/zookeeper/util/Utils.java @@ -18,16 +18,17 @@ */ package org.apache.cxf.dosgi.discovery.zookeeper.util; -import java.util.Arrays; -import java.util.Collection; +import java.util.ArrayList; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; +import java.util.List; import java.util.Map; import java.util.UUID; import java.util.regex.Matcher; import java.util.regex.Pattern; +import org.apache.aries.rsa.util.StringPlus; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.osgi.service.remoteserviceadmin.EndpointListener; @@ -46,54 +47,24 @@ public final class Utils { } /** - * Returns the value of a "string+" property as an array of strings. - * <p> - * A "string+" property can have a value which is either a string, - * an array of strings, or a collection of strings. - * <p> - * If the given value is not of one of the valid types, or is null, - * an empty array is returned. - * - * @param property a "string+" property value - * @return the property value as an array of strings, or an empty array - */ - public static String[] getStringPlusProperty(Object property) { - if (property instanceof String) { - return new String[] {(String)property}; - } else if (property instanceof String[]) { - return (String[])property; - } else if (property instanceof Collection) { - try { - @SuppressWarnings("unchecked") - Collection<String> strings = (Collection<String>)property; - return strings.toArray(new String[strings.size()]); - } catch (ArrayStoreException ase) { - // ignore collections with wrong type - } - } - return new String[0]; - } - - /** * Removes nulls and empty strings from the given string array. * * @param strings an array of strings * @return a new array containing the non-null and non-empty * elements of the original array in the same order */ - public static String[] removeEmpty(String[] strings) { - String[] result = new String[strings.length]; - int copied = 0; + public static List<String> removeEmpty(List<String> strings) { + List<String> result = new ArrayList<String>(); for (String s : strings) { if (s != null && !s.isEmpty()) { - result[copied++] = s; + result.add(s); } } - return copied == result.length ? result : Arrays.copyOf(result, copied); + return result; } - public static String[] getScopes(ServiceReference<?> sref) { - return removeEmpty(getStringPlusProperty(sref.getProperty(EndpointListener.ENDPOINT_LISTENER_SCOPE))); + public static List<String> getScopes(ServiceReference<?> sref) { + return removeEmpty(StringPlus.normalize(sref.getProperty(EndpointListener.ENDPOINT_LISTENER_SCOPE))); } // copied from the DSW OSGiUtils class
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerFactoryTest.java ---------------------------------------------------------------------- diff --git a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerFactoryTest.java b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerFactoryTest.java index e63b805..a8498fd 100644 --- a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerFactoryTest.java +++ b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerFactoryTest.java @@ -24,8 +24,8 @@ import java.util.List; import junit.framework.TestCase; import org.apache.zookeeper.ZooKeeper; -import org.easymock.classextension.EasyMock; -import org.easymock.classextension.IMocksControl; +import org.easymock.EasyMock; +import org.easymock.IMocksControl; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceRegistration; import org.osgi.service.remoteserviceadmin.EndpointListener; http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerTest.java ---------------------------------------------------------------------- diff --git a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerTest.java b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerTest.java index aa1b68e..31c2802 100644 --- a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerTest.java +++ b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/publish/PublishingEndpointListenerTest.java @@ -23,17 +23,15 @@ import java.util.HashMap; import java.util.List; import java.util.Map; -import junit.framework.TestCase; - -import org.apache.cxf.dosgi.endpointdesc.EndpointDescriptionParser; -import org.apache.cxf.dosgi.endpointdesc.PropertiesMapper; +import org.apache.aries.rsa.discovery.endpoint.EndpointDescriptionParser; +import org.apache.aries.rsa.discovery.endpoint.PropertiesMapper; import org.apache.zookeeper.CreateMode; import org.apache.zookeeper.KeeperException; import org.apache.zookeeper.ZooDefs.Ids; import org.apache.zookeeper.ZooKeeper; +import org.easymock.EasyMock; import org.easymock.IAnswer; -import org.easymock.classextension.EasyMock; -import org.easymock.classextension.IMocksControl; +import org.easymock.IMocksControl; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; import org.osgi.framework.Filter; @@ -45,6 +43,8 @@ import org.osgi.service.remoteserviceadmin.RemoteConstants; import org.osgi.xmlns.rsa.v1_0.EndpointDescriptionType; import org.osgi.xmlns.rsa.v1_0.PropertyType; +import junit.framework.TestCase; + public class PublishingEndpointListenerTest extends TestCase { public void testEndpointRemovalAdding() throws KeeperException, InterruptedException { http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorManagerTest.java ---------------------------------------------------------------------- diff --git a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorManagerTest.java b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorManagerTest.java index 7d6f67f..5e5cb63 100644 --- a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorManagerTest.java +++ b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorManagerTest.java @@ -24,9 +24,9 @@ import java.util.List; import java.util.Map; import org.apache.zookeeper.ZooKeeper; +import org.easymock.EasyMock; import org.easymock.IAnswer; -import org.easymock.classextension.EasyMock; -import org.easymock.classextension.IMocksControl; +import org.easymock.IMocksControl; import org.junit.Test; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorTest.java ---------------------------------------------------------------------- diff --git a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorTest.java b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorTest.java index 67afb16..044b360 100644 --- a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorTest.java +++ b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/subscribe/InterfaceMonitorTest.java @@ -29,8 +29,8 @@ import org.apache.zookeeper.Watcher.Event.EventType; import org.apache.zookeeper.Watcher.Event.KeeperState; import org.apache.zookeeper.ZooKeeper; import org.apache.zookeeper.data.Stat; -import org.easymock.classextension.EasyMock; -import org.easymock.classextension.IMocksControl; +import org.easymock.EasyMock; +import org.easymock.IMocksControl; import org.osgi.service.remoteserviceadmin.EndpointListener; import static org.easymock.EasyMock.eq; http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/util/UtilsTest.java ---------------------------------------------------------------------- diff --git a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/util/UtilsTest.java b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/util/UtilsTest.java index 08c830c..de4d9af 100644 --- a/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/util/UtilsTest.java +++ b/discovery/zookeeper/src/test/java/org/apache/cxf/dosgi/discovery/zookeeper/util/UtilsTest.java @@ -18,15 +18,15 @@ */ package org.apache.cxf.dosgi.discovery.zookeeper.util; -import java.util.Arrays; +import java.util.List; -import junit.framework.TestCase; - -import org.easymock.classextension.EasyMock; -import org.easymock.classextension.IMocksControl; +import org.easymock.EasyMock; +import org.easymock.IMocksControl; import org.osgi.framework.ServiceReference; import org.osgi.service.remoteserviceadmin.EndpointListener; +import junit.framework.TestCase; + public class UtilsTest extends TestCase { public void testGetZooKeeperPath() { @@ -38,57 +38,6 @@ public class UtilsTest extends TestCase { assertEquals(Utils.PATH_PREFIX, Utils.getZooKeeperPath("")); } - public void testGetStringPlusProperty() { - String[] out = Utils.getStringPlusProperty("MyString"); - assertEquals(1, out.length); - assertEquals("MyString", out[0]); - - out = Utils.getStringPlusProperty(new String[]{"MyString"}); - assertEquals(1, out.length); - assertEquals("MyString", out[0]); - - out = Utils.getStringPlusProperty(Arrays.asList("MyString")); - assertEquals(1, out.length); - assertEquals("MyString", out[0]); - - out = Utils.getStringPlusProperty(Arrays.asList(1)); - assertEquals(0, out.length); - - out = Utils.getStringPlusProperty(new Object()); - assertEquals(0, out.length); - - out = Utils.getStringPlusProperty(null); - assertEquals(0, out.length); - } - - public void testRemoveEmpty() { - String[] out = Utils.removeEmpty(new String[0]); - assertEquals(0, out.length); - - out = Utils.removeEmpty(new String[]{null}); - assertEquals(0, out.length); - - out = Utils.removeEmpty(new String[]{""}); - assertEquals(0, out.length); - - out = Utils.removeEmpty(new String[]{"hi"}); - assertEquals(1, out.length); - assertEquals("hi", out[0]); - - out = Utils.removeEmpty(new String[]{"", "hi", null}); - assertEquals(1, out.length); - assertEquals("hi", out[0]); - - out = Utils.removeEmpty(new String[]{"hi", null, "", ""}); - assertEquals(1, out.length); - assertEquals("hi", out[0]); - - out = Utils.removeEmpty(new String[]{"", "hi", null, "", "", "bye", null}); - assertEquals(2, out.length); - assertEquals("hi", out[0]); - assertEquals("bye", out[1]); - } - public void testGetScopes() { IMocksControl c = EasyMock.createNiceControl(); @@ -101,10 +50,10 @@ public class UtilsTest extends TestCase { c.replay(); - String[] ret = Utils.getScopes(sref); + List<String> ret = Utils.getScopes(sref); c.verify(); - assertEquals(1, ret.length); - assertEquals(scopes[0], ret[0]); + assertEquals(1, ret.size()); + assertEquals(scopes[0], ret.get(0)); } } http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/features/src/main/resources/features.xml ---------------------------------------------------------------------- diff --git a/features/src/main/resources/features.xml b/features/src/main/resources/features.xml index fa14ba6..4470deb 100644 --- a/features/src/main/resources/features.xml +++ b/features/src/main/resources/features.xml @@ -3,6 +3,7 @@ <repository>mvn:org.apache.cxf.karaf/apache-cxf/${cxf.version}/xml/features</repository> <feature name="aries-rsa-core" version="${project.version}"> + <bundle>mvn:org.apache.aries.rsa/spi/${project.version}</bundle> <bundle>mvn:org.apache.aries.rsa/core/${project.version}</bundle> <bundle>mvn:org.apache.aries.rsa/topology-manager/${project.version}</bundle> </feature> http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/parent/pom.xml ---------------------------------------------------------------------- diff --git a/parent/pom.xml b/parent/pom.xml index 256e06f..c30aa10 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -53,13 +53,6 @@ <dependency> <groupId>org.slf4j</groupId> <artifactId>slf4j-api</artifactId> - <version>${slf4j.version}</version> - <scope>provided</scope> - </dependency> - <dependency> - <groupId>org.apache.aries.rsa</groupId> - <artifactId>spi</artifactId> - <version>${project.version}</version> <scope>provided</scope> </dependency> @@ -108,6 +101,12 @@ <version>${slf4j.version}</version> </dependency> <dependency> + <groupId>org.apache.aries.rsa</groupId> + <artifactId>spi</artifactId> + <version>${project.version}</version> + </dependency> + + <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.12</version> @@ -131,14 +130,12 @@ <build> <defaultGoal>install</defaultGoal> - - <pluginManagement> <plugins> <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> - <version>${felix.plugin.version}</version> + <version>3.0.1</version> <extensions>true</extensions> </plugin> <plugin> @@ -168,10 +165,10 @@ <plugin> <groupId>org.apache.felix</groupId> <artifactId>maven-bundle-plugin</artifactId> - <version>3.0.1</version> <extensions>true</extensions> <configuration> <instructions> + <Export-Package>!*</Export-Package> <_include>-bnd.bnd</_include> </instructions> </configuration> http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/provider/tcp/pom.xml ---------------------------------------------------------------------- diff --git a/provider/tcp/pom.xml b/provider/tcp/pom.xml index 2edfb3b..e14a39b 100644 --- a/provider/tcp/pom.xml +++ b/provider/tcp/pom.xml @@ -19,9 +19,9 @@ <dependencies> <dependency> - <groupId>org.apache.cxf.dosgi</groupId> - <artifactId>cxf-dosgi-ri-provider-api</artifactId> - <version>${project.version}</version> + <groupId>org.apache.aries.rsa</groupId> + <artifactId>spi</artifactId> + <scope>provided</scope> </dependency> </dependencies> http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/Activator.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/Activator.java b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/Activator.java index 128c3d8..c26292a 100644 --- a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/Activator.java +++ b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/Activator.java @@ -21,7 +21,7 @@ package org.apache.aries.rsa.provider.tcp; import java.util.Dictionary; import java.util.Hashtable; -import org.apache.cxf.dosgi.dsw.api.DistributionProvider; +import org.apache.aries.rsa.spi.DistributionProvider; import org.osgi.framework.BundleActivator; import org.osgi.framework.BundleContext; import org.osgi.service.remoteserviceadmin.RemoteConstants; http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java index 07c5a05..c103abb 100644 --- a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java +++ b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TCPProvider.java @@ -23,9 +23,9 @@ import java.lang.reflect.Proxy; import java.net.URI; import java.util.Map; -import org.apache.cxf.dosgi.dsw.api.DistributionProvider; -import org.apache.cxf.dosgi.dsw.api.Endpoint; -import org.apache.cxf.dosgi.dsw.api.IntentUnsatisfiedException; +import org.apache.aries.rsa.spi.DistributionProvider; +import org.apache.aries.rsa.spi.Endpoint; +import org.apache.aries.rsa.spi.IntentUnsatisfiedException; import org.osgi.framework.BundleContext; import org.osgi.service.remoteserviceadmin.EndpointDescription; import org.osgi.service.remoteserviceadmin.RemoteConstants; http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java index 5bc9d7a..8f61e3c 100644 --- a/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java +++ b/provider/tcp/src/main/java/org/apache/aries/rsa/provider/tcp/TcpEndpoint.java @@ -21,7 +21,7 @@ package org.apache.aries.rsa.provider.tcp; import java.io.IOException; import java.util.Map; -import org.apache.cxf.dosgi.dsw.api.Endpoint; +import org.apache.aries.rsa.spi.Endpoint; import org.osgi.service.remoteserviceadmin.EndpointDescription; import org.osgi.service.remoteserviceadmin.RemoteConstants; http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java ---------------------------------------------------------------------- diff --git a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java index 583c5e1..5d57c41 100644 --- a/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java +++ b/provider/tcp/src/test/java/org/apache/aries/rsa/provider/tcp/TcpProviderTest.java @@ -27,8 +27,8 @@ import java.util.concurrent.TimeUnit; import org.apache.aries.rsa.provider.tcp.myservice.MyService; import org.apache.aries.rsa.provider.tcp.myservice.MyServiceImpl; -import org.apache.cxf.dosgi.dsw.api.Endpoint; -import org.apache.cxf.dosgi.dsw.api.EndpointHelper; +import org.apache.aries.rsa.spi.Endpoint; +import org.apache.aries.rsa.util.EndpointHelper; import org.easymock.EasyMock; import org.junit.After; import org.junit.Assert; http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/bnd.bnd ---------------------------------------------------------------------- diff --git a/rsa/bnd.bnd b/rsa/bnd.bnd index d32545d..1222aef 100644 --- a/rsa/bnd.bnd +++ b/rsa/bnd.bnd @@ -1,5 +1,3 @@ -Bundle-Activator: org.apache.cxf.dosgi.dsw.service.Activator -Export-Package: \ - org.apache.cxf.dosgi.dsw.api,\ - org.apache.cxf.dosgi.dsw.service,\ - org.osgi.service.remoteserviceadmin +Bundle-Activator: org.apache.aries.rsa.core.Activator +Private-Package: org.apache.aries.rsa.core +Export-Package: org.osgi.service.remoteserviceadmin \ No newline at end of file http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/pom.xml ---------------------------------------------------------------------- diff --git a/rsa/pom.xml b/rsa/pom.xml index b220283..d2359c0 100644 --- a/rsa/pom.xml +++ b/rsa/pom.xml @@ -20,7 +20,7 @@ <dependency> <groupId>org.apache.aries.rsa</groupId> <artifactId>spi</artifactId> - <version>${project.version}</version> + <scope>provided</scope> </dependency> </dependencies> http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/Activator.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/Activator.java b/rsa/src/main/java/org/apache/aries/rsa/core/Activator.java new file mode 100644 index 0000000..cb347f4 --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/Activator.java @@ -0,0 +1,37 @@ +/** + * 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 org.osgi.framework.BundleActivator; +import org.osgi.framework.BundleContext; + +public class Activator implements BundleActivator { + + private DistributionProviderTracker tracker; + + public void start(BundleContext bundlecontext) throws Exception { + tracker = new DistributionProviderTracker(bundlecontext); + tracker.open(); + } + + public void stop(BundleContext context) throws Exception { + tracker.close(); + } + +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/ClientServiceFactory.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/ClientServiceFactory.java b/rsa/src/main/java/org/apache/aries/rsa/core/ClientServiceFactory.java new file mode 100644 index 0000000..54bbc54 --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/ClientServiceFactory.java @@ -0,0 +1,110 @@ +/** + * 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.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.aries.rsa.spi.DistributionProvider; +import org.apache.aries.rsa.spi.IntentUnsatisfiedException; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceFactory; +import org.osgi.framework.ServiceRegistration; +import org.osgi.framework.wiring.BundleWiring; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("rawtypes") +public class ClientServiceFactory implements ServiceFactory { + + private static final Logger LOG = LoggerFactory.getLogger(ClientServiceFactory.class); + + private EndpointDescription endpoint; + private DistributionProvider handler; + private ImportRegistrationImpl importRegistration; + + private boolean closeable; + private int serviceCounter; + + public ClientServiceFactory(EndpointDescription endpoint, + DistributionProvider handler, ImportRegistrationImpl ir) { + this.endpoint = endpoint; + this.handler = handler; + this.importRegistration = ir; + } + + public Object getService(final Bundle requestingBundle, final ServiceRegistration sreg) { + List<String> interfaceNames = endpoint.getInterfaces(); + final BundleContext consumerContext = requestingBundle.getBundleContext(); + final ClassLoader consumerLoader = requestingBundle.adapt(BundleWiring.class).getClassLoader(); + try { + LOG.debug("getService() from serviceFactory for {}", interfaceNames); + final List<Class<?>> interfaces = new ArrayList<Class<?>>(); + for (String ifaceName : interfaceNames) { + interfaces.add(consumerLoader.loadClass(ifaceName)); + } + Object proxy = AccessController.doPrivileged(new PrivilegedAction<Object>() { + public Object run() { + Class<?>[] ifAr = interfaces.toArray(new Class[]{}); + return handler.importEndpoint(consumerLoader, consumerContext, ifAr, endpoint); + } + }); + + synchronized (this) { + serviceCounter++; + } + return proxy; + } catch (IntentUnsatisfiedException iue) { + LOG.info("Did not create proxy for {} because intent {} could not be satisfied", + interfaceNames, iue.getIntent()); + } catch (Exception e) { + LOG.warn("Problem creating a remote proxy for {}", interfaceNames, e); + } + return null; + } + + public void ungetService(Bundle requestingBundle, ServiceRegistration sreg, Object serviceObject) { + String[] interfaces = (String[])sreg.getReference().getProperty(org.osgi.framework.Constants.OBJECTCLASS); + LOG.info("Releasing a client object, interfaces: {}", Arrays.toString(interfaces)); + + synchronized (this) { + serviceCounter--; + LOG.debug("Services still provided by this ServiceFactory: {}", serviceCounter); + closeIfUnused(); + } + } + + public void setCloseable(boolean closeable) { + synchronized (this) { + this.closeable = closeable; + closeIfUnused(); + } + } + + private synchronized void closeIfUnused() { + if (serviceCounter <= 0 && closeable) { + importRegistration.closeAll(); + } + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/DistributionProviderTracker.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/DistributionProviderTracker.java b/rsa/src/main/java/org/apache/aries/rsa/core/DistributionProviderTracker.java new file mode 100644 index 0000000..4c3d36c --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/DistributionProviderTracker.java @@ -0,0 +1,73 @@ +/** + * 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.Dictionary; +import java.util.Hashtable; + +import org.apache.aries.rsa.spi.DistributionProvider; +import org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.FrameworkUtil; +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin; +import org.osgi.util.tracker.ServiceTracker; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("rawtypes") +public class DistributionProviderTracker extends ServiceTracker<DistributionProvider, ServiceRegistration> { + private static final Logger LOG = LoggerFactory.getLogger(Activator.class); + + public DistributionProviderTracker(BundleContext context) { + super(context, DistributionProvider.class, null); + } + + @Override + public ServiceRegistration addingService(ServiceReference<DistributionProvider> reference) { + LOG.debug("RemoteServiceAdmin Implementation is starting up"); + DistributionProvider provider = context.getService(reference); + BundleContext apiContext = getAPIContext(); + RemoteServiceAdminCore rsaCore = new RemoteServiceAdminCore(context, + apiContext, + provider); + RemoteServiceadminFactory rsaf = new RemoteServiceadminFactory(rsaCore); + Dictionary<String, Object> props = new Hashtable<String, Object>(); + props.put("remote.intents.supported", reference.getProperty("remote.intents.supported")); + props.put("remote.configs.supported", reference.getProperty("remote.configs.supported")); + LOG.info("Registering RemoteServiceAdmin for provider " + provider.getClass().getName()); + return context.registerService(RemoteServiceAdmin.class.getName(), rsaf, props); + } + + protected BundleContext getAPIContext() { + Bundle apiBundle = FrameworkUtil.getBundle(DistributionProvider.class); + BundleContext apiContext = apiBundle.getBundleContext(); + return apiContext; + } + + @Override + public void removedService(ServiceReference<DistributionProvider> reference, + ServiceRegistration reg) { + LOG.debug("RemoteServiceAdmin Implementation is shutting down now"); + reg.unregister(); + super.removedService(reference, reg); + } + +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/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 new file mode 100644 index 0000000..e59c0ef --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/EventAdminHelper.java @@ -0,0 +1,151 @@ +/** + * 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/5f4c6604/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 new file mode 100644 index 0000000..4098201 --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/EventProducer.java @@ -0,0 +1,114 @@ +/** + * 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.List; + +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.ExportRegistration; +import org.osgi.service.remoteserviceadmin.ImportRegistration; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminEvent; +import org.osgi.service.remoteserviceadmin.RemoteServiceAdminListener; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +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) { + for (ExportRegistration exportRegistration : erl) { + publishNotification(exportRegistration); + } + } + + protected void publishNotification(ExportRegistration er) { + int type = er.getException() == null + ? RemoteServiceAdminEvent.EXPORT_REGISTRATION + : RemoteServiceAdminEvent.EXPORT_ERROR; + notify(type, null, er); + } + + protected void publishNotification(ImportRegistration ir) { + int type = ir.getException() == null + ? RemoteServiceAdminEvent.IMPORT_REGISTRATION + : RemoteServiceAdminEvent.IMPORT_ERROR; + notify(type, ir, null); + } + + public void notifyRemoval(ExportRegistration er) { + notify(RemoteServiceAdminEvent.EXPORT_UNREGISTRATION, null, er); + } + + public void notifyRemoval(ImportRegistration ir) { + notify(RemoteServiceAdminEvent.IMPORT_UNREGISTRATION, ir, 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) { + try { + RemoteServiceAdminEvent event = ir != null + ? new RemoteServiceAdminEvent(type, bctx.getBundle(), ir.getImportReference(), ir.getException()) + : new RemoteServiceAdminEvent(type, bctx.getBundle(), er.getExportReference(), er.getException()); + notifyListeners(event); + eaHelper.notifyEventAdmin(event); + } catch (IllegalStateException ise) { + LOG.debug("can't send notifications since bundle context is no longer valid"); + } + } + + @SuppressWarnings({ + "rawtypes", "unchecked" + }) + private void notifyListeners(RemoteServiceAdminEvent rsae) { + try { + ServiceReference[] listenerRefs = bctx.getServiceReferences( + RemoteServiceAdminListener.class.getName(), null); + if (listenerRefs != null) { + for (ServiceReference sref : listenerRefs) { + RemoteServiceAdminListener rsal = (RemoteServiceAdminListener)bctx.getService(sref); + if (rsal != null) { + try { + Bundle bundle = sref.getBundle(); + if (bundle != null) { + LOG.debug("notify RemoteServiceAdminListener {} of bundle {}", + rsal, bundle.getSymbolicName()); + rsal.remoteAdminEvent(rsae); + } + } finally { + bctx.ungetService(sref); + } + } + } + } + } catch (InvalidSyntaxException e) { + LOG.error(e.getMessage(), e); + } + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/ExportReferenceImpl.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/ExportReferenceImpl.java b/rsa/src/main/java/org/apache/aries/rsa/core/ExportReferenceImpl.java new file mode 100644 index 0000000..1366d56 --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/ExportReferenceImpl.java @@ -0,0 +1,77 @@ +/** + * 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 org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ExportReference; + +@SuppressWarnings("rawtypes") +public class ExportReferenceImpl implements ExportReference { + + private ServiceReference serviceReference; + private EndpointDescription endpoint; + + public ExportReferenceImpl(ServiceReference serviceReference, EndpointDescription endpoint) { + this.serviceReference = serviceReference; + this.endpoint = endpoint; + } + + public ExportReferenceImpl(ExportReference exportReference) { + this(exportReference.getExportedService(), exportReference.getExportedEndpoint()); + } + + public EndpointDescription getExportedEndpoint() { + return endpoint; + } + + public ServiceReference getExportedService() { + return serviceReference; + } + + @Override + public int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + (endpoint == null ? 0 : endpoint.hashCode()); + result = prime * result + (serviceReference == null ? 0 : serviceReference.hashCode()); + return result; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj == null || getClass() != obj.getClass()) { + return false; + } + ExportReferenceImpl other = (ExportReferenceImpl) obj; + boolean ed = endpoint == null ? other.endpoint == null + : endpoint.equals(other.endpoint); + boolean sr = serviceReference == null ? other.serviceReference == null + : serviceReference.equals(other.serviceReference); + return ed && sr; + } + + synchronized void close() { + this.endpoint = null; + this.serviceReference = null; + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/ExportRegistrationImpl.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/ExportRegistrationImpl.java b/rsa/src/main/java/org/apache/aries/rsa/core/ExportRegistrationImpl.java new file mode 100644 index 0000000..5a1dd66 --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/ExportRegistrationImpl.java @@ -0,0 +1,152 @@ +/** + * 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.io.Closeable; +import java.io.IOException; +import java.util.Arrays; +import java.util.Map; +import java.util.Set; + +import org.apache.aries.rsa.spi.Endpoint; +import org.osgi.framework.ServiceReference; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ExportReference; +import org.osgi.service.remoteserviceadmin.ExportRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("rawtypes") +public class ExportRegistrationImpl implements ExportRegistration { + + private static final Logger LOG = LoggerFactory.getLogger(ExportRegistrationImpl.class); + + private final RemoteServiceAdminCore rsaCore; + private final ExportReferenceImpl exportReference; + private final Closeable server; + private final Throwable exception; + + private final ExportRegistrationImpl parent; + private int instanceCount; + private volatile boolean closed; + + private ExportRegistrationImpl(ExportRegistrationImpl parent, RemoteServiceAdminCore rsaCore, + ExportReferenceImpl exportReference, Closeable server, Throwable exception) { + this.parent = parent != null ? parent.parent : this; // a parent points to itself + this.parent.addInstance(); + this.rsaCore = rsaCore; + this.exportReference = exportReference; + this.server = server; + this.exception = exception; + } + + // create a clone of the provided ExportRegistrationImpl that is linked to it + public ExportRegistrationImpl(ExportRegistrationImpl parent) { + this(parent, parent.rsaCore, new ExportReferenceImpl(parent.exportReference), + parent.server, parent.exception); + } + + // create a new (parent) instance which was exported successfully with the given server + public ExportRegistrationImpl(ServiceReference sref, Endpoint endpoint, RemoteServiceAdminCore rsaCore) { + this(null, rsaCore, new ExportReferenceImpl(sref, endpoint.description()), endpoint, null); + } + + // create a new (parent) instance which failed to be exported with the given exception + public ExportRegistrationImpl(RemoteServiceAdminCore rsaCore, Throwable exception) { + this(null, rsaCore, null, null, exception); + } + + private void ensureParent() { + if (parent != this) { + throw new IllegalStateException("this method may only be called on the parent"); + } + } + + public ExportReference getExportReference() { + if (exportReference == null) { + throw new IllegalStateException(getException()); + } + return closed ? null : exportReference; + } + + public Throwable getException() { + return closed ? null : exception; + } + + public final void close() { + synchronized (this) { + if (closed) { + return; + } + closed = true; + } + + rsaCore.removeExportRegistration(this); + exportReference.close(); + parent.removeInstance(); + } + + private void addInstance() { + ensureParent(); + synchronized (this) { + instanceCount++; + } + } + + private void removeInstance() { + ensureParent(); + synchronized (this) { + instanceCount--; + if (instanceCount <= 0) { + LOG.debug("really closing ExportRegistration now!"); + + if (server != null) { + try { + server.close(); + } catch (IOException e) { + LOG.warn("Error closing ExportRegistration", e); + } + } + } + } + } + + @Override + public String toString() { + if (closed) { + return "ExportRegistration closed"; + } + EndpointDescription endpoint = getExportReference().getExportedEndpoint(); + ServiceReference serviceReference = getExportReference().getExportedService(); + String r = "EndpointDescription for ServiceReference " + serviceReference; + + r += "\n*** EndpointDescription: ****\n"; + if (endpoint == null) { + r += "---> NULL <---- \n"; + } else { + Set<Map.Entry<String, Object>> props = endpoint.getProperties().entrySet(); + for (Map.Entry<String, Object> entry : props) { + Object value = entry.getValue(); + r += entry.getKey() + " => " + + (value instanceof Object[] ? Arrays.toString((Object[]) value) : value) + "\n"; + } + } + return r; + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/ImportRegistrationImpl.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/ImportRegistrationImpl.java b/rsa/src/main/java/org/apache/aries/rsa/core/ImportRegistrationImpl.java new file mode 100644 index 0000000..680d2af --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/ImportRegistrationImpl.java @@ -0,0 +1,230 @@ +/** + * 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.ArrayList; +import java.util.List; + +import org.osgi.framework.ServiceReference; +import org.osgi.framework.ServiceRegistration; +import org.osgi.service.remoteserviceadmin.EndpointDescription; +import org.osgi.service.remoteserviceadmin.ImportReference; +import org.osgi.service.remoteserviceadmin.ImportRegistration; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("rawtypes") +public class ImportRegistrationImpl implements ImportRegistration, ImportReference { + + private static final Logger LOG = LoggerFactory.getLogger(ImportRegistrationImpl.class); + + private volatile Throwable exception; + private volatile ServiceRegistration importedService; // used only in parent + private EndpointDescription endpoint; + private volatile ClientServiceFactory clientServiceFactory; + private RemoteServiceAdminCore rsaCore; + private boolean closed; + private boolean detached; // used only in parent + + private ImportRegistrationImpl parent; + private List<ImportRegistrationImpl> children; // used only in parent + + public ImportRegistrationImpl(Throwable ex) { + exception = ex; + initParent(); + } + + public ImportRegistrationImpl(EndpointDescription endpoint, RemoteServiceAdminCore rsac) { + this.endpoint = endpoint; + this.rsaCore = rsac; + initParent(); + } + + /** + * Creates a clone of the given parent instance. + */ + public ImportRegistrationImpl(ImportRegistrationImpl ir) { + // we always want a link to the parent... + parent = ir.getParent(); + exception = parent.getException(); + endpoint = parent.getImportedEndpointDescription(); + clientServiceFactory = parent.clientServiceFactory; + rsaCore = parent.rsaCore; + + parent.instanceAdded(this); + } + + private void initParent() { + parent = this; + children = new ArrayList<ImportRegistrationImpl>(1); + } + + private void ensureParent() { + if (parent != this) { + throw new IllegalStateException("this method may only be called on the parent"); + } + } + + /** + * Called on parent when a child is added. + * + * @param iri the child + */ + private synchronized void instanceAdded(ImportRegistrationImpl iri) { + ensureParent(); + children.add(iri); + } + + /** + * Called on parent when a child is closed. + * + * @param iri the child + */ + private void instanceClosed(ImportRegistrationImpl iri) { + ensureParent(); + synchronized (this) { + children.remove(iri); + if (!children.isEmpty() || detached || !closed) { + return; + } + detached = true; + } + + LOG.debug("really closing ImportRegistration now"); + + if (importedService != null) { + try { + importedService.unregister(); + } catch (IllegalStateException ise) { + LOG.debug("imported service is already unregistered"); + } + importedService = null; + } + if (clientServiceFactory != null) { + clientServiceFactory.setCloseable(true); + } + } + + public void close() { + LOG.debug("close() called"); + + synchronized (this) { + if (isInvalid()) { + return; + } + closed = true; + } + rsaCore.removeImportRegistration(this); + parent.instanceClosed(this); + } + + /** + * Closes all ImportRegistrations which share the same parent as this one. + */ + public void closeAll() { + if (this == parent) { + LOG.info("closing down all child ImportRegistrations"); + + // we must iterate over a copy of children since close() removes the child + // from the list (which would cause a ConcurrentModificationException) + for (ImportRegistrationImpl ir : copyChildren()) { + ir.close(); + } + this.close(); + } else { + parent.closeAll(); + } + } + + private List<ImportRegistrationImpl> copyChildren() { + synchronized (this) { + return new ArrayList<ImportRegistrationImpl>(children); + } + } + + public EndpointDescription getImportedEndpointDescription() { + return isInvalid() ? null : endpoint; + } + + @Override + public EndpointDescription getImportedEndpoint() { + return getImportedEndpointDescription(); + } + + @Override + public ServiceReference getImportedService() { + return isInvalid() || parent.importedService == null ? null : parent.importedService.getReference(); + } + + @Override + public ImportReference getImportReference() { + return this; + } + + @Override + public Throwable getException() { + return exception; + } + + public void setException(Throwable ex) { + exception = ex; + } + + private synchronized boolean isInvalid() { + return exception != null || closed; + } + + /** + * Sets the {@link ServiceRegistration} representing the locally + * registered {@link ClientServiceFactory} service which provides + * proxies to the remote imported service. It is set only on the parent. + * + * @param sreg the ServiceRegistration + */ + public void setImportedServiceRegistration(ServiceRegistration sreg) { + ensureParent(); + importedService = sreg; + } + + /** + * Sets the {@link ClientServiceFactory} which is the implementation + * of the locally registered service which provides proxies to the + * remote imported service. It is set only on the parent. + * + * @param csf the ClientServiceFactory + */ + public void setClientServiceFactory(ClientServiceFactory csf) { + ensureParent(); + clientServiceFactory = csf; + } + + public ImportRegistrationImpl getParent() { + return parent; + } + + /** + * Returns the imported endpoint even if this + * instance is closed or has an exception. + * + * @return the imported endpoint + */ + public EndpointDescription getImportedEndpointAlways() { + return endpoint; + } +} http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/5f4c6604/rsa/src/main/java/org/apache/aries/rsa/core/PackageUtil.java ---------------------------------------------------------------------- diff --git a/rsa/src/main/java/org/apache/aries/rsa/core/PackageUtil.java b/rsa/src/main/java/org/apache/aries/rsa/core/PackageUtil.java new file mode 100644 index 0000000..fe58bdf --- /dev/null +++ b/rsa/src/main/java/org/apache/aries/rsa/core/PackageUtil.java @@ -0,0 +1,85 @@ +/** + * 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 org.osgi.framework.Bundle; +import org.osgi.framework.BundleContext; +import org.osgi.framework.ServiceReference; +import org.osgi.service.packageadmin.ExportedPackage; +import org.osgi.service.packageadmin.PackageAdmin; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +@SuppressWarnings("deprecation") +public final class PackageUtil { + + public static final Logger LOG = LoggerFactory.getLogger(PackageUtil.class); + + private PackageUtil() { + } + + /** + * Tries to retrieve the version of iClass via the PackageAdmin. + * + * @param iClass tThe interface for which the version should be found + * @param bc any valid BundleContext + * @return the version of the interface or "0.0.0" if no version information could be found or an error + * occurred during the retrieval + */ + public static String getVersion(Class<?> iClass, BundleContext bc) { + ServiceReference<PackageAdmin> paRef = bc.getServiceReference(PackageAdmin.class); + if (paRef != null) { + PackageAdmin pa = bc.getService(paRef); + try { + Bundle b = pa.getBundle(iClass); + if (b == null) { + LOG.info("Unable to find interface version for interface " + iClass.getName() + + ". Falling back to 0.0.0"); + return "0.0.0"; + } + LOG.debug("Interface source bundle: {}", b.getSymbolicName()); + + ExportedPackage[] ep = pa.getExportedPackages(b); + LOG.debug("Exported Packages of the source bundle: {}", (Object)ep); + + String pack = iClass.getPackage().getName(); + LOG.debug("Looking for Package: {}", pack); + if (ep != null) { + for (ExportedPackage p : ep) { + if (p != null + && pack.equals(p.getName())) { + LOG.debug("found package -> Version: {}", p.getVersion()); + return p.getVersion().toString(); + } + } + } + } finally { + if (pa != null) { + bc.ungetService(paRef); + } + } + } else { + LOG.error("Was unable to obtain the package admin service -> can't resolve interface versions"); + } + + LOG.info("Unable to find interface version for interface " + iClass.getName() + + ". Falling back to 0.0.0"); + return "0.0.0"; + } +}
