You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@aries.apache.org by cs...@apache.org on 2016/03/11 20:43:21 UTC
[22/50] [abbrv] aries-rsa git commit: Switch project setup to Aries
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/TestExportService.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/TestExportService.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/TestExportService.java
deleted file mode 100644
index fa4a63e..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/TestExportService.java
+++ /dev/null
@@ -1,137 +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.cxf.dosgi.systests2.multi;
-
-import java.io.IOException;
-import java.net.URL;
-import java.util.Map;
-
-import javax.xml.parsers.DocumentBuilder;
-import javax.xml.parsers.DocumentBuilderFactory;
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.w3c.dom.Document;
-import org.w3c.dom.Element;
-import org.xml.sax.SAXException;
-import org.apache.cxf.dosgi.samples.greeter.GreeterData;
-import org.apache.cxf.dosgi.samples.greeter.GreeterException;
-import org.apache.cxf.dosgi.samples.greeter.GreeterService;
-import org.apache.cxf.dosgi.samples.greeter.GreetingPhrase;
-import org.apache.cxf.frontend.ClientProxyFactoryBean;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-
-import static org.ops4j.pax.exam.CoreOptions.frameworkStartLevel;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-
-@RunWith(PaxExam.class)
-public class TestExportService extends AbstractDosgiTest {
-
- @Configuration
- public static Option[] configure() throws Exception {
- return new Option[] {
- MultiBundleTools.getDistroWithDiscovery(),
- systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"),
- mavenBundle().groupId("org.apache.servicemix.bundles")
- .artifactId("org.apache.servicemix.bundles.junit").version("4.9_2"),
- mavenBundle().groupId("org.apache.cxf.dosgi.samples")
- .artifactId("cxf-dosgi-ri-samples-greeter-interface").versionAsInProject(),
- mavenBundle().groupId("org.apache.cxf.dosgi.samples")
- .artifactId("cxf-dosgi-ri-samples-greeter-impl").versionAsInProject(),
- mavenBundle().groupId("org.apache.cxf.dosgi.systests")
- .artifactId("cxf-dosgi-ri-systests2-common").versionAsInProject(), frameworkStartLevel(100),
- //CoreOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005")
- };
- }
-
- @Test
- public void testAccessEndpoint() throws Exception {
- assertBundlesStarted();
- waitPort(9090);
-
- checkWsdl(new URL("http://localhost:9090/greeter?wsdl"));
-
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- Thread.currentThread().setContextClassLoader(ClientProxyFactoryBean.class.getClassLoader());
- try {
- checkServiceCall("http://localhost:9090/greeter");
- } finally {
- Thread.currentThread().setContextClassLoader(cl);
- }
- }
-
- private void checkServiceCall(String serviceUri) {
- GreeterService client = createGreeterServiceProxy(serviceUri);
-
- Map<GreetingPhrase, String> greetings = client.greetMe("Fred");
- Assert.assertEquals("Fred", greetings.get(new GreetingPhrase("Hello")));
- System.out.println("Invocation result: " + greetings);
-
- try {
- GreeterData gd = new GreeterDataImpl("Stranger", 11, true);
- client.greetMe(gd);
- Assert.fail("GreeterException has to be thrown");
- } catch (GreeterException ex) {
- Assert.assertEquals("Wrong exception message", "GreeterService can not greet Stranger",
- ex.toString());
- }
- }
-
- private void checkWsdl(URL wsdlURL) throws ParserConfigurationException, SAXException, IOException {
- DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
- dbf.setNamespaceAware(true);
- dbf.setValidating(false);
- DocumentBuilder db = dbf.newDocumentBuilder();
- Document doc = db.parse(wsdlURL.openStream());
- Element el = doc.getDocumentElement();
- Assert.assertEquals("definitions", el.getLocalName());
- Assert.assertEquals("http://schemas.xmlsoap.org/wsdl/", el.getNamespaceURI());
- Assert.assertEquals("GreeterService", el.getAttribute("name"));
- }
-
- class GreeterDataImpl implements GreeterData {
-
- private String name;
- private int age;
- private boolean exception;
-
- GreeterDataImpl(String n, int a, boolean ex) {
- name = n;
- age = a;
- exception = ex;
- }
-
- public String getName() {
- return name;
- }
-
- public int getAge() {
- return age;
- }
-
- public boolean isException() {
- return exception;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/TestImportService.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/TestImportService.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/TestImportService.java
deleted file mode 100644
index efc334b..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/TestImportService.java
+++ /dev/null
@@ -1,161 +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.cxf.dosgi.systests2.multi;
-
-import java.io.InputStream;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.Map;
-
-import javax.inject.Inject;
-
-import org.apache.cxf.aegis.databinding.AegisDatabinding;
-import org.apache.cxf.dosgi.samples.greeter.GreeterData;
-import org.apache.cxf.dosgi.samples.greeter.GreeterException;
-import org.apache.cxf.dosgi.samples.greeter.GreeterService;
-import org.apache.cxf.dosgi.samples.greeter.GreetingPhrase;
-import org.apache.cxf.dosgi.systests2.common.test1.GreeterDataImpl;
-import org.apache.cxf.dosgi.systests2.common.test1.MyActivator;
-import org.apache.cxf.dosgi.systests2.common.test1.MyServiceTracker;
-import org.apache.cxf.dosgi.systests2.common.test1.StartServiceTracker;
-import org.apache.cxf.endpoint.Server;
-import org.apache.cxf.frontend.ServerFactoryBean;
-import org.junit.Assert;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.ops4j.pax.exam.Configuration;
-import org.ops4j.pax.exam.Option;
-import org.ops4j.pax.exam.junit.PaxExam;
-import org.ops4j.pax.tinybundles.core.TinyBundles;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-
-import static org.ops4j.pax.exam.CoreOptions.frameworkStartLevel;
-import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
-import static org.ops4j.pax.exam.CoreOptions.provision;
-import static org.ops4j.pax.exam.CoreOptions.systemProperty;
-
-@RunWith(PaxExam.class)
-public class TestImportService extends AbstractDosgiTest {
-
- @Inject
- BundleContext bundleContext;
-
- @Configuration
- public static Option[] configure() throws Exception {
- return new Option[] {
- MultiBundleTools.getDistroWithDiscovery(),
- systemProperty("org.ops4j.pax.logging.DefaultServiceLog.level").value("INFO"),
- mavenBundle().groupId("org.apache.cxf.dosgi.samples")
- .artifactId("cxf-dosgi-ri-samples-greeter-interface").versionAsInProject(),
- mavenBundle().groupId("org.apache.servicemix.bundles")
- .artifactId("org.apache.servicemix.bundles.junit").version("4.9_2"),
- mavenBundle().groupId("org.apache.cxf.dosgi.systests")
- .artifactId("cxf-dosgi-ri-systests2-common").versionAsInProject(),
- provision(createServiceConsumerBundle()),
- // increase for debugging
- systemProperty("org.apache.cxf.dosgi.test.serviceWaitTimeout").value(
- System.getProperty("org.apache.cxf.dosgi.test.serviceWaitTimeout", "200")),
- frameworkStartLevel(100),
- //CoreOptions.vmOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005")
- };
- }
-
- protected static InputStream createServiceConsumerBundle() {
- return TinyBundles.bundle()
- .add(MyActivator.class)
- .add(MyServiceTracker.class)
- .add(StartServiceTracker.class)
- .add(GreeterDataImpl.class)
- .add("OSGI-INF/remote-service/remote-services.xml", TestImportService.class.getResource("/rs-test1.xml"))
- .set(Constants.BUNDLE_SYMBOLICNAME, "testClientBundle")
- .set(Constants.EXPORT_PACKAGE, "org.apache.cxf.dosgi.systests2.common.test1")
- .set(Constants.BUNDLE_ACTIVATOR, MyActivator.class.getName())
- .build(TinyBundles.withBnd());
- }
-
- @Test
- public void testClientConsumer() throws Exception {
- // This test tests the consumer side of Distributed OSGi. It works as follows:
- // 1. It creates a little test bundle on the fly and starts that in the framework
- // (this happens in the configure() method above). The test bundle waits until its
- // instructed to start doing stuff. It's give this instruction via a service that is
- // registered by this test (the service is of type java.lang.Object and has testName=test1).
- // 2. The test manually creates a CXF server of the appropriate type (using ServerFactoryBean)
- // 3. It signals the client bundle by registering a service to start doing its work.
- // This registers a ServiceTracker in the client bundle for the remote service that is created
- // by the test in step 2. The client bundle knows about the address through the
- // remote-services.xml file.
- // 4. The client bundle will invoke the remote service and record the results in a service that it
- // registers in the Service Registry.
- // 5. The test waits for this service to appear and then checks the results which are available as
- // a service property.
-
- // Set up a Server in the test
- Server server = null;
- try {
- server = publishTestGreeter();
-
- Dictionary<String, Object> props = new Hashtable<String, Object>();
- props.put("testName", "test1");
- bundleContext.registerService(Object.class.getName(), new Object(), props);
-
- // Wait for the service tracker in the test bundle to register a service with the test result
- @SuppressWarnings("rawtypes")
- ServiceReference ref = waitService(bundleContext, String.class, "(testResult=test1)", 20);
- Assert.assertEquals("HiOSGi;exception", ref.getProperty("result"));
- } finally {
- if (server != null) {
- server.stop();
- }
-
- }
- }
-
- private Server publishTestGreeter() {
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- try {
- Thread.currentThread().setContextClassLoader(ServerFactoryBean.class.getClassLoader());
- ServerFactoryBean factory = new ServerFactoryBean();
- factory.setServiceClass(GreeterService.class);
- factory.setAddress("http://localhost:9191/grrr");
- factory.getServiceFactory().setDataBinding(new AegisDatabinding());
- factory.setServiceBean(new TestGreeter());
- return factory.create();
- } finally {
- Thread.currentThread().setContextClassLoader(cl);
- }
- }
-
- public static class TestGreeter implements GreeterService {
-
- public Map<GreetingPhrase, String> greetMe(String name) {
- Map<GreetingPhrase, String> m = new HashMap<GreetingPhrase, String>();
- GreetingPhrase gp = new GreetingPhrase("Hi");
- m.put(gp, name);
- return m;
- }
-
- public GreetingPhrase[] greetMe(GreeterData gd) throws GreeterException {
- throw new GreeterException("TestGreeter");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/AddGreetingPhraseInterceptor.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/AddGreetingPhraseInterceptor.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/AddGreetingPhraseInterceptor.java
deleted file mode 100644
index a3a19be..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/AddGreetingPhraseInterceptor.java
+++ /dev/null
@@ -1,44 +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.cxf.dosgi.systests2.multi.customintent;
-
-import java.util.List;
-import java.util.Map;
-
-import org.apache.cxf.dosgi.samples.greeter.GreetingPhrase;
-import org.apache.cxf.helpers.CastUtils;
-import org.apache.cxf.interceptor.Fault;
-import org.apache.cxf.message.Message;
-import org.apache.cxf.message.MessageContentsList;
-import org.apache.cxf.phase.AbstractPhaseInterceptor;
-
-public final class AddGreetingPhraseInterceptor extends AbstractPhaseInterceptor<Message> {
-
- AddGreetingPhraseInterceptor(String phase) {
- super(phase);
- }
-
- public void handleMessage(Message message) throws Fault {
- MessageContentsList contents = (MessageContentsList) message.getContent(List.class);
- Map<GreetingPhrase, String> result = CastUtils.cast((Map<?, ?>)contents.get(0));
- result.put(new GreetingPhrase("Hi from custom intent"), "customintent");
- //Object content1 = contents.iterator().next();
- System.out.println(message);
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/CustomFeature.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/CustomFeature.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/CustomFeature.java
deleted file mode 100644
index abac14f..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/CustomFeature.java
+++ /dev/null
@@ -1,33 +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.cxf.dosgi.systests2.multi.customintent;
-
-import org.apache.cxf.Bus;
-import org.apache.cxf.feature.AbstractFeature;
-import org.apache.cxf.interceptor.InterceptorProvider;
-import org.apache.cxf.phase.Phase;
-
-public final class CustomFeature extends AbstractFeature {
-
- @Override
- protected void initializeProvider(InterceptorProvider provider, Bus bus) {
- provider.getOutInterceptors().add(0, new AddGreetingPhraseInterceptor(Phase.USER_LOGICAL));
- super.initializeProvider(provider, bus);
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/CustomIntentActivator.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/CustomIntentActivator.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/CustomIntentActivator.java
deleted file mode 100644
index ca4efda..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/CustomIntentActivator.java
+++ /dev/null
@@ -1,37 +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.cxf.dosgi.systests2.multi.customintent;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-public class CustomIntentActivator implements BundleActivator {
-
- public void start(BundleContext context) throws Exception {
- Dictionary<String, String> props = new Hashtable<String, String>();
- props.put("org.apache.cxf.dosgi.IntentName", "myIntent");
- context.registerService(Object.class.getName(), new CustomFeature(), props);
- }
-
- public void stop(BundleContext context) throws Exception {
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/service/EmptyGreeterService.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/service/EmptyGreeterService.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/service/EmptyGreeterService.java
deleted file mode 100644
index 2c0108d..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/service/EmptyGreeterService.java
+++ /dev/null
@@ -1,41 +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.cxf.dosgi.systests2.multi.customintent.service;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import org.apache.cxf.dosgi.samples.greeter.GreeterData;
-import org.apache.cxf.dosgi.samples.greeter.GreeterException;
-import org.apache.cxf.dosgi.samples.greeter.GreeterService;
-import org.apache.cxf.dosgi.samples.greeter.GreetingPhrase;
-
-public final class EmptyGreeterService implements GreeterService {
-
- /**
- * Return an empty array. Our custom intent should add a GreetingPhrase
- */
- public GreetingPhrase[] greetMe(GreeterData name) throws GreeterException {
- return new GreetingPhrase[]{};
- }
-
- public Map<GreetingPhrase, String> greetMe(String name) {
- return new HashMap<GreetingPhrase, String>();
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/service/GreeterServiceWithCustomIntentActivator.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/service/GreeterServiceWithCustomIntentActivator.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/service/GreeterServiceWithCustomIntentActivator.java
deleted file mode 100644
index bcf6016..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/customintent/service/GreeterServiceWithCustomIntentActivator.java
+++ /dev/null
@@ -1,42 +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.cxf.dosgi.systests2.multi.customintent.service;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.apache.cxf.dosgi.samples.greeter.GreeterService;
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-import org.osgi.service.remoteserviceadmin.RemoteConstants;
-
-public class GreeterServiceWithCustomIntentActivator implements BundleActivator {
-
- public void start(BundleContext context) throws Exception {
- Dictionary<String, String> props = new Hashtable<String, String>();
- props.put(RemoteConstants.SERVICE_EXPORTED_INTERFACES, "*");
- props.put(RemoteConstants.SERVICE_EXPORTED_CONFIGS, "org.apache.cxf.ws");
- props.put("org.apache.cxf.ws.address", "http://localhost:9090/greeter");
- props.put(RemoteConstants.SERVICE_EXPORTED_INTENTS, "myIntent");
- context.registerService(GreeterService.class.getName(), new EmptyGreeterService(), props);
- }
-
- public void stop(BundleContext context) throws Exception {
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/RestTranslate.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/RestTranslate.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/RestTranslate.java
deleted file mode 100644
index 3a55c0e..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/RestTranslate.java
+++ /dev/null
@@ -1,34 +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.cxf.dosgi.systests2.multi.rest;
-
-import javax.ws.rs.GET;
-import javax.ws.rs.Path;
-import javax.ws.rs.PathParam;
-
-public interface RestTranslate {
-
- @GET
- String englishWords();
-
- @GET
- @Path("/{word}")
- String getTranslation(@PathParam("word") String word);
-
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/RestTranslateImpl.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/RestTranslateImpl.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/RestTranslateImpl.java
deleted file mode 100644
index 640b0c9..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/RestTranslateImpl.java
+++ /dev/null
@@ -1,41 +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.cxf.dosgi.systests2.multi.rest;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class RestTranslateImpl implements RestTranslate {
- Map<String, String> translation;
-
- public RestTranslateImpl() {
- translation = new HashMap<String, String>();
- translation.put("hello", "hallo");
- }
-
- @Override
- public String englishWords() {
- return translation.keySet().toString();
- }
-
- @Override
- public String getTranslation(String word) {
- return translation.get(word);
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/TranslateActivator.java
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/TranslateActivator.java b/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/TranslateActivator.java
deleted file mode 100644
index 1c48fb5..0000000
--- a/systests2/multi-bundle/src/test/java/org/apache/cxf/dosgi/systests2/multi/rest/TranslateActivator.java
+++ /dev/null
@@ -1,40 +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.cxf.dosgi.systests2.multi.rest;
-
-import java.util.Dictionary;
-import java.util.Hashtable;
-
-import org.osgi.framework.BundleActivator;
-import org.osgi.framework.BundleContext;
-
-public class TranslateActivator implements BundleActivator {
-
- public void start(BundleContext context) throws Exception {
- Dictionary<String, String> props = new Hashtable<String, String>();
- props.put("service.exported.interfaces", "*");
- props.put("service.exported.configs", "org.apache.cxf.rs");
- props.put("service.exported.intents", "HTTP");
- props.put("org.apache.cxf.rs.address", "/translate");
- context.registerService(RestTranslate.class.getName(), new RestTranslateImpl(), props);
- }
-
- public void stop(BundleContext context) throws Exception {
- }
-}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/multi-bundle/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/systests2/multi-bundle/src/test/resources/log4j.properties b/systests2/multi-bundle/src/test/resources/log4j.properties
deleted file mode 100644
index 2f206d5..0000000
--- a/systests2/multi-bundle/src/test/resources/log4j.properties
+++ /dev/null
@@ -1,13 +0,0 @@
-# Set root logger level to DEBUG and its only appender to A1.
-log4j.rootLogger=INFO, A1
-
-# A1 is set to be a ConsoleAppender.
-log4j.appender.A1=org.apache.log4j.ConsoleAppender
-
-# A1 uses PatternLayout.
-log4j.appender.A1.layout=org.apache.log4j.PatternLayout
-log4j.appender.A1.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
-
-log4j.logger.org.ops4j.pax.scanner=WARN
-log4j.logger.org.ops4j.pax.runner=WARN
-log4j.logger.org.ops4j.pax.url=WARN
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/systests2/pom.xml
----------------------------------------------------------------------
diff --git a/systests2/pom.xml b/systests2/pom.xml
deleted file mode 100644
index 93d70e2..0000000
--- a/systests2/pom.xml
+++ /dev/null
@@ -1,42 +0,0 @@
-<?xml version='1.0' encoding='UTF-8' ?>
-<!--
- 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.
--->
-<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/maven-v4_0_0.xsd">
-
- <modelVersion>4.0.0</modelVersion>
-
- <parent>
- <groupId>org.apache.cxf.dosgi</groupId>
- <artifactId>cxf-dosgi-ri-parent</artifactId>
- <version>1.8-SNAPSHOT</version>
- <relativePath>../parent/pom.xml</relativePath>
- </parent>
-
- <groupId>org.apache.cxf.dosgi.systests</groupId>
- <artifactId>cxf-dosgi-ri-systests2</artifactId>
- <version>1.8-SNAPSHOT</version>
- <packaging>pom</packaging>
-
- <name>Distributed OSGi System Tests</name>
-
- <modules>
- <module>common</module>
- <module>multi-bundle</module>
- </modules>
-</project>
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/bnd.bnd
----------------------------------------------------------------------
diff --git a/topology-manager/bnd.bnd b/topology-manager/bnd.bnd
new file mode 100644
index 0000000..3ff22e0
--- /dev/null
+++ b/topology-manager/bnd.bnd
@@ -0,0 +1 @@
+Bundle-Activator: org.apache.cxf.dosgi.topologymanager.Activator
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/pom.xml
----------------------------------------------------------------------
diff --git a/topology-manager/pom.xml b/topology-manager/pom.xml
new file mode 100644
index 0000000..2df803e
--- /dev/null
+++ b/topology-manager/pom.xml
@@ -0,0 +1,47 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+ 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.
+-->
+<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/maven-v4_0_0.xsd">
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <parent>
+ <groupId>org.apache.aries.rsa</groupId>
+ <artifactId>parent</artifactId>
+ <version>1.8-SNAPSHOT</version>
+ <relativePath>../parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>topology-manager</artifactId>
+ <packaging>bundle</packaging>
+ <name>Aries Remote Service Admin Topology Manager</name>
+
+ <properties>
+ <topDirectoryLocation>..</topDirectoryLocation>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <version>1.3</version>
+ </dependency>
+ </dependencies>
+
+</project>
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/Activator.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/Activator.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/Activator.java
new file mode 100644
index 0000000..62ec1a9
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/Activator.java
@@ -0,0 +1,192 @@
+/**
+ * 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.cxf.dosgi.topologymanager;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.cxf.dosgi.dsw.api.ExportPolicy;
+import org.apache.cxf.dosgi.topologymanager.exporter.DefaultExportPolicy;
+import org.apache.cxf.dosgi.topologymanager.exporter.EndpointListenerNotifier;
+import org.apache.cxf.dosgi.topologymanager.exporter.EndpointRepository;
+import org.apache.cxf.dosgi.topologymanager.exporter.TopologyManagerExport;
+import org.apache.cxf.dosgi.topologymanager.importer.TopologyManagerImport;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.remoteserviceadmin.EndpointListener;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Activator implements BundleActivator {
+ public static final String RSA_EXPORT_POLICY_FILTER = "rsa.export.policy.filter";
+ static final String DOSGI_SERVICES = "(" + RemoteConstants.SERVICE_EXPORTED_INTERFACES + "=*)";
+ private static final Logger LOG = LoggerFactory.getLogger(Activator.class);
+
+ private TopologyManagerExport exportManager;
+ private TopologyManagerImport importManager;
+ private EndpointListenerNotifier notifier;
+ private ServiceTracker<RemoteServiceAdmin, RemoteServiceAdmin> rsaTracker;
+ private ThreadPoolExecutor exportExecutor;
+ private ServiceTracker<EndpointListener, EndpointListener> epListenerTracker;
+ private ServiceTracker<ExportPolicy, ExportPolicy> policyTracker;
+
+ public void start(final BundleContext bc) throws Exception {
+ Dictionary<String, String> props = new Hashtable<String, String>();
+ props.put("name", "default");
+ bc.registerService(ExportPolicy.class, new DefaultExportPolicy(), props);
+
+ Filter policyFilter = exportPolicyFilter(bc);
+ policyTracker = new ServiceTracker<ExportPolicy, ExportPolicy>(bc, policyFilter, null) {
+
+ @Override
+ public ExportPolicy addingService(ServiceReference<ExportPolicy> reference) {
+ ExportPolicy policy = super.addingService(reference);
+ if (exportManager == null) {
+ doStart(bc, policy);
+ }
+ return policy;
+ }
+
+ @Override
+ public void removedService(ServiceReference<ExportPolicy> reference, ExportPolicy service) {
+ if (exportManager != null) {
+ doStop(bc);
+ }
+ super.removedService(reference, service);
+ }
+ };
+ policyTracker.open();
+ }
+
+ private Filter exportPolicyFilter(BundleContext bc) throws InvalidSyntaxException {
+ String filter = bc.getProperty(RSA_EXPORT_POLICY_FILTER);
+ if (filter == null) {
+ filter = "(name=default)";
+ }
+ return FrameworkUtil.createFilter(String.format("(&(objectClass=%s)%s)", ExportPolicy.class.getName(), filter));
+ }
+
+ public void doStart(final BundleContext bc, ExportPolicy policy) {
+ LOG.debug("TopologyManager: start()");
+ EndpointRepository endpointRepo = new EndpointRepository();
+ notifier = new EndpointListenerNotifier(endpointRepo);
+ epListenerTracker = new EndpointListenerTracker(bc);
+ endpointRepo.setNotifier(notifier);
+ exportExecutor = new ThreadPoolExecutor(5, 10, 50, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
+ exportManager = new TopologyManagerExport(endpointRepo, exportExecutor, policy);
+ importManager = new TopologyManagerImport(bc);
+ rsaTracker = new RSATracker(bc, RemoteServiceAdmin.class, null);
+ bc.addServiceListener(exportManager);
+ rsaTracker.open();
+ epListenerTracker.open();
+ exportExistingServices(bc);
+ importManager.start();
+ }
+
+ public void stop(BundleContext bc) throws Exception {
+ policyTracker.close();
+ }
+
+ public void doStop(BundleContext bc) {
+ LOG.debug("TopologyManager: stop()");
+ epListenerTracker.close();
+ bc.removeServiceListener(exportManager);
+ exportExecutor.shutdown();
+ importManager.stop();
+ rsaTracker.close();
+ exportManager = null;
+ }
+
+ public void exportExistingServices(BundleContext context) {
+ try {
+ // cast to String is necessary for compiling against OSGi core version >= 4.3
+ ServiceReference<?>[] references = context.getServiceReferences((String)null, DOSGI_SERVICES);
+ if (references != null) {
+ for (ServiceReference<?> sref : references) {
+ exportManager.serviceChanged(new ServiceEvent(ServiceEvent.REGISTERED, sref));
+ }
+ }
+ } catch (InvalidSyntaxException e) {
+ LOG.error("Error in filter {}. This should not occur!", DOSGI_SERVICES);
+ }
+ }
+
+ private final class EndpointListenerTracker extends ServiceTracker<EndpointListener, EndpointListener> {
+ private EndpointListenerTracker(BundleContext context) {
+ super(context, EndpointListener.class, null);
+ }
+
+ @Override
+ public EndpointListener addingService(ServiceReference<EndpointListener> reference) {
+ EndpointListener listener = super.addingService(reference);
+ notifier.add(listener, EndpointListenerNotifier.getFiltersFromEndpointListenerScope(reference));
+ return listener;
+ }
+
+ @Override
+ public void modifiedService(ServiceReference<EndpointListener> reference,
+ EndpointListener listener) {
+ super.modifiedService(reference, listener);
+ notifier.add(listener, EndpointListenerNotifier.getFiltersFromEndpointListenerScope(reference));
+ }
+
+ @Override
+ public void removedService(ServiceReference<EndpointListener> reference,
+ EndpointListener listener) {
+ notifier.remove(listener);
+ super.removedService(reference, listener);
+ }
+ }
+
+ private final class RSATracker extends ServiceTracker<RemoteServiceAdmin, RemoteServiceAdmin> {
+ private RSATracker(BundleContext context, Class<RemoteServiceAdmin> clazz,
+ ServiceTrackerCustomizer<RemoteServiceAdmin, RemoteServiceAdmin> customizer) {
+ super(context, clazz, customizer);
+ }
+
+ @Override
+ public RemoteServiceAdmin addingService(ServiceReference<RemoteServiceAdmin> reference) {
+ RemoteServiceAdmin rsa = super.addingService(reference);
+ LOG.debug("New RemoteServiceAdmin {} detected, trying to import and export services with it", rsa);
+ importManager.add(rsa);
+ exportManager.add(rsa);
+ return rsa;
+ }
+
+ @Override
+ public void removedService(ServiceReference<RemoteServiceAdmin> reference,
+ RemoteServiceAdmin rsa) {
+ exportManager.remove(rsa);
+ importManager.remove(rsa);
+ super.removedService(reference, rsa);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/DefaultExportPolicy.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/DefaultExportPolicy.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/DefaultExportPolicy.java
new file mode 100644
index 0000000..689ebab
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/DefaultExportPolicy.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.cxf.dosgi.topologymanager.exporter;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.cxf.dosgi.dsw.api.ExportPolicy;
+import org.osgi.framework.ServiceReference;
+
+/**
+ * The default is to not customize the way services are exported
+ */
+public class DefaultExportPolicy implements ExportPolicy {
+
+ @Override
+ public Map<String, ?> additionalParameters(ServiceReference<?> sref) {
+ return new HashMap<String, Object>();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/EndpointListenerNotifier.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/EndpointListenerNotifier.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/EndpointListenerNotifier.java
new file mode 100644
index 0000000..13d7dab
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/EndpointListenerNotifier.java
@@ -0,0 +1,133 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.dosgi.topologymanager.exporter;
+
+import java.util.Dictionary;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.osgi.service.remoteserviceadmin.EndpointListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Tracks EndpointListeners and allows to notify them of endpoints.
+ */
+public class EndpointListenerNotifier implements EndpointListener {
+ private static final Logger LOG = LoggerFactory.getLogger(EndpointListenerNotifier.class);
+ private enum NotifyType { ADDED, REMOVED };
+ private Map<EndpointListener, Set<Filter>> listeners;
+ private EndpointRepository endpointRepo;
+
+ public EndpointListenerNotifier(final EndpointRepository endpointRepo) {
+ this.endpointRepo = endpointRepo;
+ this.listeners = new ConcurrentHashMap<EndpointListener, Set<Filter>>();
+ }
+
+ public static Set<Filter> getFiltersFromEndpointListenerScope(ServiceReference<EndpointListener> sref) {
+ Set<Filter> filters = new HashSet<Filter>();
+ String[] scopes = StringPlus.parse(sref.getProperty(EndpointListener.ENDPOINT_LISTENER_SCOPE));
+ for (String scope : scopes) {
+ try {
+ filters.add(FrameworkUtil.createFilter(scope));
+ } catch (InvalidSyntaxException e) {
+ LOG.error("invalid endpoint listener scope: {}", scope, e);
+ }
+ }
+ return filters;
+ }
+
+ public void add(EndpointListener ep, Set<Filter> filters) {
+ LOG.debug("new EndpointListener detected");
+ listeners.put(ep, filters);
+ for (EndpointDescription endpoint : endpointRepo.getAllEndpoints()) {
+ notifyListener(NotifyType.ADDED, ep, filters, endpoint);
+ }
+ }
+
+ public void remove(EndpointListener ep) {
+ LOG.debug("EndpointListener modified");
+ listeners.remove(ep);
+ }
+
+ @Override
+ public void endpointAdded(EndpointDescription endpoint, String matchedFilter) {
+ notifyListeners(NotifyType.ADDED, endpoint);
+ }
+
+ @Override
+ public void endpointRemoved(EndpointDescription endpoint, String matchedFilter) {
+ notifyListeners(NotifyType.REMOVED, endpoint);
+ }
+
+ /**
+ * Notifies all endpoint listeners about endpoints being added or removed.
+ *
+ * @param added specifies whether endpoints were added (true) or removed (false)
+ * @param endpoints the endpoints the listeners should be notified about
+ */
+ private void notifyListeners(NotifyType type, EndpointDescription endpoint) {
+ for (EndpointListener listener : listeners.keySet()) {
+ notifyListener(type, listener, listeners.get(listener), endpoint);
+ }
+ }
+
+ /**
+ * Notifies an endpoint listener about endpoints being added or removed.
+ *
+ * @param type specifies whether endpoints were added (true) or removed (false)
+ * @param endpointListenerRef the ServiceReference of an EndpointListener to notify
+ * @param endpoints the endpoints the listener should be notified about
+ */
+ private void notifyListener(NotifyType type, EndpointListener listener, Set<Filter> filters,
+ EndpointDescription endpoint) {
+ LOG.debug("Endpoint {}", type);
+ Set<Filter> matchingFilters = getMatchingFilters(filters, endpoint);
+ for (Filter filter : matchingFilters) {
+ if (type == NotifyType.ADDED) {
+ listener.endpointAdded(endpoint, filter.toString());
+ } else {
+ listener.endpointRemoved(endpoint, filter.toString());
+ }
+ }
+ }
+
+ private static Set<Filter> getMatchingFilters(Set<Filter> filters, EndpointDescription endpoint) {
+ Set<Filter> matchingFilters = new HashSet<Filter>();
+ Dictionary<String, Object> dict = new Hashtable<String, Object>(endpoint.getProperties());
+ for (Filter filter : filters) {
+ if (filter.match(dict)) {
+ LOG.debug("Filter {} matches endpoint {}", filter, dict);
+ matchingFilters.add(filter);
+ } else {
+ LOG.trace("Filter {} does not match endpoint {}", filter, dict);
+ }
+ }
+ return matchingFilters;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/EndpointRepository.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/EndpointRepository.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/EndpointRepository.java
new file mode 100644
index 0000000..2a7bab3
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/EndpointRepository.java
@@ -0,0 +1,140 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.dosgi.topologymanager.exporter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.remoteserviceadmin.EndpointDescription;
+import org.osgi.service.remoteserviceadmin.EndpointListener;
+import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Holds all endpoints that are exported by a TopologyManager. For each ServiceReference that is exported a
+ * map is maintained which contains information on the endpoints for each RemoteAdminService that created the
+ * endpoints.
+ */
+@SuppressWarnings("rawtypes")
+public class EndpointRepository {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EndpointRepository.class);
+
+ private final Map<ServiceReference, Map<RemoteServiceAdmin, Collection<EndpointDescription>>> exportedServices
+ = new LinkedHashMap<ServiceReference, Map<RemoteServiceAdmin, Collection<EndpointDescription>>>();
+
+ private EndpointListener notifier;
+
+ public void setNotifier(EndpointListener notifier) {
+ this.notifier = notifier;
+ }
+
+
+ /**
+ * Remove all services exported by the given rsa.
+ *
+ * @param rsa the RemoteServiceAdmin to remove
+ * @return list of removed endpoints
+ */
+ public synchronized List<EndpointDescription> removeRemoteServiceAdmin(RemoteServiceAdmin rsa) {
+ LOG.debug("RemoteServiceAdmin removed: {}", rsa.getClass().getName());
+ List<EndpointDescription> removedEndpoints = new ArrayList<EndpointDescription>();
+ for (Map<RemoteServiceAdmin, Collection<EndpointDescription>> exports : exportedServices.values()) {
+ Collection<EndpointDescription> endpoints = exports.get(rsa);
+ if (endpoints != null) {
+ removedEndpoints.addAll(endpoints);
+ exports.remove(rsa);
+ }
+ }
+ endpointsRemoved(removedEndpoints);
+ return removedEndpoints;
+ }
+
+ public synchronized void removeService(ServiceReference sref) {
+ List<EndpointDescription> removedEndpoints = new ArrayList<EndpointDescription>();
+ Map<RemoteServiceAdmin, Collection<EndpointDescription>> rsaToEndpoints = exportedServices.get(sref);
+ if (rsaToEndpoints != null) {
+ for (Collection<EndpointDescription> endpoints : rsaToEndpoints.values()) {
+ removedEndpoints.addAll(endpoints);
+ }
+ exportedServices.remove(sref);
+ }
+ endpointsRemoved(removedEndpoints);
+ }
+
+ public synchronized void addService(ServiceReference sref) {
+ if (!exportedServices.containsKey(sref)) {
+ LOG.info("Marking service from bundle {} for export", sref.getBundle().getSymbolicName());
+ exportedServices.put(sref, new LinkedHashMap<RemoteServiceAdmin, Collection<EndpointDescription>>());
+ }
+ }
+
+ public synchronized void addEndpoints(ServiceReference sref, RemoteServiceAdmin rsa,
+ List<EndpointDescription> endpoints) {
+ addService(sref);
+ Map<RemoteServiceAdmin, Collection<EndpointDescription>> exports = exportedServices.get(sref);
+ exports.put(rsa, endpoints);
+ endpointsAdded(endpoints);
+ }
+
+ synchronized boolean isAlreadyExportedForRsa(ServiceReference sref, RemoteServiceAdmin rsa) {
+ Map<RemoteServiceAdmin, Collection<EndpointDescription>> exports = exportedServices.get(sref);
+ return exports != null && exports.containsKey(rsa);
+ }
+
+ public synchronized Collection<EndpointDescription> getAllEndpoints() {
+ List<EndpointDescription> allEndpoints = new ArrayList<EndpointDescription>();
+ for (Map<RemoteServiceAdmin, Collection<EndpointDescription>> exports : exportedServices.values()) {
+ for (Collection<EndpointDescription> endpoints : exports.values()) {
+ allEndpoints.addAll(endpoints);
+ }
+ }
+ return allEndpoints;
+ }
+
+ public synchronized Set<ServiceReference> getServicesToBeExportedFor(RemoteServiceAdmin rsa) {
+ Set<ServiceReference> servicesToBeExported = new HashSet<ServiceReference>();
+ for (Map.Entry<ServiceReference, Map<RemoteServiceAdmin, Collection<EndpointDescription>>> entry
+ : exportedServices.entrySet()) {
+ if (!entry.getValue().containsKey(rsa)) {
+ servicesToBeExported.add(entry.getKey());
+ }
+ }
+ return servicesToBeExported;
+ }
+
+ private void endpointsAdded(List<EndpointDescription> endpoints) {
+ for (EndpointDescription epd : endpoints) {
+ notifier.endpointAdded(epd, null);
+ }
+ }
+
+ private void endpointsRemoved(List<EndpointDescription> endpoints) {
+ for (EndpointDescription epd : endpoints) {
+ notifier.endpointRemoved(epd, null);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/StringPlus.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/StringPlus.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/StringPlus.java
new file mode 100644
index 0000000..1198154
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/StringPlus.java
@@ -0,0 +1,57 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.cxf.dosgi.topologymanager.exporter;
+
+import java.util.Collection;
+
+public final class StringPlus {
+
+ private StringPlus() {
+ }
+
+ /**
+ * 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[] parse(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];
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/TopologyManagerExport.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/TopologyManagerExport.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/TopologyManagerExport.java
new file mode 100644
index 0000000..ad3736c
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/exporter/TopologyManagerExport.java
@@ -0,0 +1,195 @@
+/**
+ * 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.cxf.dosgi.topologymanager.exporter;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.Executor;
+
+import org.apache.cxf.dosgi.dsw.api.ExportPolicy;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+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.osgi.service.remoteserviceadmin.RemoteConstants;
+import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages exported endpoints of DOSGi services and notifies EndpointListeners of changes.
+ *
+ * <li> Tracks local RemoteServiceAdmin instances by using a ServiceTracker
+ * <li> Uses a ServiceListener to track local OSGi services
+ * <li> When a service is published that is supported by DOSGi the
+ * known RemoteServiceAdmins are instructed to export the service and
+ * the EndpointListeners are notified
+ * <li> When a service is unpublished the EndpointListeners are notified.
+ * The endpoints are not closed as the ExportRegistration takes care of this
+ */
+public class TopologyManagerExport implements ServiceListener {
+ private static final Logger LOG = LoggerFactory.getLogger(TopologyManagerExport.class);
+
+ private final Executor execService;
+ private final EndpointRepository endpointRepo;
+ private ExportPolicy policy;
+ private final Set<RemoteServiceAdmin> rsaSet;
+
+
+ public TopologyManagerExport(final EndpointRepository endpointRepo, Executor executor, ExportPolicy policy) {
+ this.endpointRepo = endpointRepo;
+ this.policy = policy;
+ this.rsaSet = new HashSet<RemoteServiceAdmin>();
+ this.execService = executor;
+ }
+
+ // track all service registrations so we can export any services that are configured to be exported
+ // ServiceListener events may be delivered out of order, concurrently, re-entrant, etc. (see spec or docs)
+ public void serviceChanged(ServiceEvent event) {
+ ServiceReference<?> sref = event.getServiceReference();
+ if (event.getType() == ServiceEvent.REGISTERED) {
+ LOG.debug("Received REGISTERED ServiceEvent: {}", event);
+ export(sref);
+ } else if (event.getType() == ServiceEvent.UNREGISTERING) {
+ LOG.debug("Received UNREGISTERING ServiceEvent: {}", event);
+ endpointRepo.removeService(sref);
+ }
+ }
+
+ public void add(RemoteServiceAdmin rsa) {
+ rsaSet.add(rsa);
+ for (ServiceReference<?> serviceRef : endpointRepo.getServicesToBeExportedFor(rsa)) {
+ export(serviceRef);
+ }
+ };
+
+ public void remove(RemoteServiceAdmin rsa) {
+ rsaSet.remove(rsa);
+ endpointRepo.removeRemoteServiceAdmin(rsa);
+ };
+
+ private void export(final ServiceReference<?> sref) {
+ execService.execute(new Runnable() {
+ public void run() {
+ doExport(sref);
+ }
+ });
+ }
+
+ private void doExport(final ServiceReference<?> sref) {
+ Map<String, ?> addProps = policy.additionalParameters(sref);
+ if (!shouldExport(sref, addProps)) {
+ LOG.debug("Skipping service {}", sref);
+ return;
+ }
+ LOG.debug("Exporting service {}", sref);
+ endpointRepo.addService(sref); // mark for future export even if there are currently no RSAs
+ if (rsaSet.size() == 0) {
+ LOG.error("No RemoteServiceAdmin available! Unable to export service from bundle {}, interfaces: {}",
+ getSymbolicName(sref.getBundle()),
+ sref.getProperty(org.osgi.framework.Constants.OBJECTCLASS));
+ return;
+ }
+
+ for (RemoteServiceAdmin remoteServiceAdmin : rsaSet) {
+ LOG.info("TopologyManager: handling remoteServiceAdmin " + remoteServiceAdmin);
+ if (endpointRepo.isAlreadyExportedForRsa(sref, remoteServiceAdmin)) {
+ // already handled by this remoteServiceAdmin
+ LOG.debug("already handled by this remoteServiceAdmin -> skipping");
+ } else {
+
+ exportServiceUsingRemoteServiceAdmin(sref, remoteServiceAdmin, addProps);
+ }
+ }
+ }
+
+ private boolean shouldExport(ServiceReference<?> sref, Map<String, ?> addProps) {
+ String exported = (String)sref.getProperty(RemoteConstants.SERVICE_EXPORTED_INTERFACES);
+ String addExported = (String)addProps.get(RemoteConstants.SERVICE_EXPORTED_INTERFACES);
+ String effectiveExported = addExported != null ? addExported : exported;
+ return (effectiveExported != null) && !effectiveExported.isEmpty();
+ }
+
+ private Object getSymbolicName(Bundle bundle) {
+ return bundle == null ? null : bundle.getSymbolicName();
+ }
+
+ private void exportServiceUsingRemoteServiceAdmin(final ServiceReference<?> sref,
+ final RemoteServiceAdmin remoteServiceAdmin,
+ Map<String, ?> addProps) {
+ // abort if the service was unregistered by the time we got here
+ // (we check again at the end, but this optimization saves unnecessary heavy processing)
+ if (sref.getBundle() == null) {
+ LOG.info("TopologyManager: export aborted for {} since it was unregistered", sref);
+ endpointRepo.removeService(sref);
+ return;
+ }
+ // do the export
+ LOG.debug("exporting {}...", sref);
+ // TODO: additional parameter Map?
+ Collection<ExportRegistration> exportRegs = remoteServiceAdmin.exportService(sref, addProps);
+ // process successful/failed registrations
+ List<EndpointDescription> endpoints = new ArrayList<EndpointDescription>();
+ for (ExportRegistration reg : exportRegs) {
+ if (reg.getException() == null) {
+ EndpointDescription endpoint = getExportedEndpoint(reg);
+ LOG.info("TopologyManager: export succeeded for {}, endpoint ", sref, endpoint);
+ endpoints.add(endpoint);
+ } else {
+ LOG.error("TopologyManager: export failed for {}", sref);
+ reg.close();
+ }
+ }
+ // abort export if service was unregistered in the meanwhile (since we have a race
+ // with the unregister event which may have already been handled, so we'll miss it)
+ if (sref.getBundle() == null) {
+ LOG.info("TopologyManager: export reverted for {} since service was unregistered", sref);
+ endpointRepo.removeService(sref);
+ for (ExportRegistration reg : exportRegs) {
+ reg.close();
+ }
+ return;
+ }
+ // add the new exported endpoints
+ if (!endpoints.isEmpty()) {
+ LOG.info("TopologyManager: export successful for {}, endpoints: {}", sref, endpoints);
+ endpointRepo.addEndpoints(sref, remoteServiceAdmin, endpoints);
+ }
+ }
+
+ /**
+ * Retrieves an exported Endpoint (while safely handling nulls).
+ *
+ * @param exReg an export registration
+ * @return exported Endpoint or null if not present
+ */
+ private EndpointDescription getExportedEndpoint(ExportRegistration exReg) {
+ ExportReference ref = (exReg == null) ? null : exReg.getExportReference();
+ return (ref == null) ? null : ref.getExportedEndpoint();
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/EndpointListenerManager.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/EndpointListenerManager.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/EndpointListenerManager.java
new file mode 100644
index 0000000..7812e52
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/EndpointListenerManager.java
@@ -0,0 +1,98 @@
+/**
+ * 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.cxf.dosgi.topologymanager.importer;
+
+import java.util.ArrayList;
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.List;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.remoteserviceadmin.EndpointListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Manages an EndpointListener and adjusts its scope according to requested service filters.
+ */
+public class EndpointListenerManager {
+
+ private static final Logger LOG = LoggerFactory.getLogger(EndpointListenerManager.class);
+
+ private final BundleContext bctx;
+ private volatile ServiceRegistration<EndpointListener> serviceRegistration;
+ private final List<String> filters = new ArrayList<String>();
+ private final EndpointListener endpointListener;
+
+ public EndpointListenerManager(BundleContext bc, EndpointListener endpointListener) {
+ this.bctx = bc;
+ this.endpointListener = endpointListener;
+ }
+
+ protected void start() {
+ serviceRegistration = bctx.registerService(EndpointListener.class, endpointListener,
+ getRegistrationProperties());
+ }
+
+ public void stop() {
+ if (serviceRegistration != null) {
+ serviceRegistration.unregister();
+ }
+ }
+
+ protected void extendScope(String filter) {
+ if (filter == null) {
+ return;
+ }
+ LOG.debug("EndpointListener: extending scope by {}", filter);
+ synchronized (filters) {
+ filters.add(filter);
+ }
+ updateRegistration();
+ }
+
+ protected void reduceScope(String filter) {
+ if (filter == null) {
+ return;
+ }
+ LOG.debug("EndpointListener: reducing scope by {}", filter);
+ synchronized (filters) {
+ filters.remove(filter);
+ }
+ updateRegistration();
+ }
+
+ private Dictionary<String, Object> getRegistrationProperties() {
+ Dictionary<String, Object> p = new Hashtable<String, Object>();
+
+ synchronized (filters) {
+ LOG.debug("Current filter: {}", filters);
+ p.put(EndpointListener.ENDPOINT_LISTENER_SCOPE, new ArrayList<String>(filters));
+ }
+
+ return p;
+ }
+
+ private void updateRegistration() {
+ if (serviceRegistration != null) {
+ serviceRegistration.setProperties(getRegistrationProperties());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/FilterHelper.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/FilterHelper.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/FilterHelper.java
new file mode 100644
index 0000000..3739f16
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/FilterHelper.java
@@ -0,0 +1,43 @@
+/**
+ * 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.cxf.dosgi.topologymanager.importer;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.osgi.framework.Constants;
+
+public final class FilterHelper {
+ private static final String OBJECTCLASS_EXPRESSION = ".*\\(" + Constants.OBJECTCLASS + "=([a-zA-Z_0-9.]+)\\).*";
+ private static final Pattern OBJECTCLASS_PATTERN = Pattern.compile(OBJECTCLASS_EXPRESSION);
+
+ private FilterHelper() {
+ // prevent instantiation
+ }
+
+ public static String getObjectClass(String filter) {
+ if (filter != null) {
+ Matcher matcher = OBJECTCLASS_PATTERN.matcher(filter);
+ if (matcher.matches() && matcher.groupCount() >= 1) {
+ return matcher.group(1);
+ }
+ }
+ return null;
+ }
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/ListenerHookImpl.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/ListenerHookImpl.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/ListenerHookImpl.java
new file mode 100644
index 0000000..03ec9da
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/ListenerHookImpl.java
@@ -0,0 +1,119 @@
+/**
+ * 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.cxf.dosgi.topologymanager.importer;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.hooks.service.ListenerHook;
+import org.osgi.service.remoteserviceadmin.RemoteConstants;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Listens for service listeners and informs ServiceInterestListener about added and removed interest
+ * in services
+ */
+public class ListenerHookImpl implements ListenerHook {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ListenerHookImpl.class);
+
+ // From the old impl.
+ private static final Set<String> SYSTEM_PACKAGES;
+ static {
+ SYSTEM_PACKAGES = new HashSet<String>();
+ SYSTEM_PACKAGES.add("org.osgi.service");
+ SYSTEM_PACKAGES.add("org.apache.felix");
+ SYSTEM_PACKAGES.add("org.ops4j.pax.logging");
+ SYSTEM_PACKAGES.add("ch.ethz.iks.slp");
+ SYSTEM_PACKAGES.add("org.ungoverned.osgi.service");
+ SYSTEM_PACKAGES.add("org.springframework.osgi.context.event.OsgiBundleApplicationContextListener");
+ SYSTEM_PACKAGES.add("java.net.ContentHandler");
+ }
+
+ private final BundleContext bctx;
+ private final ServiceInterestListener serviceInterestListener;
+ private final String frameworkUUID;
+
+ public ListenerHookImpl(BundleContext bc, ServiceInterestListener serviceInterestListener) {
+ this.bctx = bc;
+ this.frameworkUUID = bctx.getProperty(Constants.FRAMEWORK_UUID);
+ this.serviceInterestListener = serviceInterestListener;
+ }
+
+ @Override
+ public void added(Collection<ListenerInfo> listeners) {
+ LOG.debug("added listeners {}", listeners);
+ for (ListenerInfo listenerInfo : listeners) {
+ LOG.debug("Filter {}", listenerInfo.getFilter());
+
+ String className = FilterHelper.getObjectClass(listenerInfo.getFilter());
+
+ if (listenerInfo.getBundleContext().equals(bctx)) {
+ LOG.debug("ListenerHookImpl: skipping request from myself");
+ continue;
+ }
+
+ if (listenerInfo.getFilter() == null) {
+ LOG.debug("skipping empty filter");
+ continue;
+ }
+
+ if (isClassExcluded(className)) {
+ LOG.debug("Skipping import request for excluded class [{}]", className);
+ continue;
+ }
+ String exFilter = extendFilter(listenerInfo.getFilter());
+ serviceInterestListener.addServiceInterest(exFilter);
+ }
+ }
+
+ @Override
+ public void removed(Collection<ListenerInfo> listeners) {
+ LOG.debug("removed listeners {}", listeners);
+
+ for (ListenerInfo listenerInfo : listeners) {
+ LOG.debug("Filter {}", listenerInfo.getFilter());
+
+ // TODO: determine if service was handled?
+ String exFilter = extendFilter(listenerInfo.getFilter());
+ serviceInterestListener.removeServiceInterest(exFilter);
+ }
+ }
+
+ private static boolean isClassExcluded(String className) {
+ if (className == null) {
+ return true;
+ }
+
+ for (String p : SYSTEM_PACKAGES) {
+ if (className.startsWith(p)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ String extendFilter(String filter) {
+ return "(&" + filter + "(!(" + RemoteConstants.ENDPOINT_FRAMEWORK_UUID + "=" + frameworkUUID + ")))";
+ }
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/RSATracker.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/RSATracker.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/RSATracker.java
new file mode 100644
index 0000000..56e98e8
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/RSATracker.java
@@ -0,0 +1,26 @@
+/**
+ * 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.cxf.dosgi.topologymanager.importer;
+
+import org.osgi.service.remoteserviceadmin.RemoteServiceAdmin;
+
+public interface RSATracker {
+ void added(RemoteServiceAdmin rsa);
+ void removed(RemoteServiceAdmin rsa);
+}
http://git-wip-us.apache.org/repos/asf/aries-rsa/blob/d73a3a7f/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/ReferenceCounter.java
----------------------------------------------------------------------
diff --git a/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/ReferenceCounter.java b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/ReferenceCounter.java
new file mode 100644
index 0000000..6ecff31
--- /dev/null
+++ b/topology-manager/src/main/java/org/apache/cxf/dosgi/topologymanager/importer/ReferenceCounter.java
@@ -0,0 +1,76 @@
+/**
+ * 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.cxf.dosgi.topologymanager.importer;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * Manages a reference count per key.
+ *
+ * @param <K> the key type
+ */
+public class ReferenceCounter<K> {
+
+ private final ConcurrentMap<K, Integer> counts = new ConcurrentHashMap<K, Integer>();
+
+ /**
+ * Increases the reference count for the given key,
+ * or sets it to 1 if the key has no existing count.
+ *
+ * @param key a key
+ * @return the updated reference count
+ */
+ public int add(K key) {
+ while (true) {
+ Integer count = counts.get(key);
+ if (count == null) {
+ if (counts.putIfAbsent(key, 1) == null) {
+ return 1;
+ }
+ } else if (counts.replace(key, count, count + 1)) {
+ return count + 1;
+ }
+ }
+ }
+
+ /**
+ * Decreases the reference count for the given key,
+ * and removes it if it reaches 0.
+ * If the key has no existing count, -1 is returned.
+ *
+ * @param key a key
+ * @return the updated reference count, or -1 if the key has no existing count
+ */
+ public int remove(K key) {
+ while (true) {
+ Integer count = counts.get(key);
+ if (count == null) {
+ return -1;
+ }
+ if (count == 1) {
+ if (counts.remove(key, 1)) {
+ return 0;
+ }
+ } else if (counts.replace(key, count, count - 1)) {
+ return count - 1;
+ }
+ }
+ }
+}