You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by jb...@apache.org on 2016/05/19 16:54:06 UTC

[1/2] activemq-artemis git commit: This closes #526

Repository: activemq-artemis
Updated Branches:
  refs/heads/master 6204aaac5 -> 0ae419e58


This closes #526


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/0ae419e5
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/0ae419e5
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/0ae419e5

Branch: refs/heads/master
Commit: 0ae419e58151214ebd0628656fa82555e54e22b7
Parents: 6204aaa e994eda
Author: jbertram <jb...@apache.org>
Authored: Thu May 19 11:53:31 2016 -0500
Committer: jbertram <jb...@apache.org>
Committed: Thu May 19 11:53:31 2016 -0500

----------------------------------------------------------------------
 artemis-features/pom.xml                        |   1 +
 .../src/main/resources/features.xml             |  16 +-
 docs/user-manual/en/karaf.md                    |   2 +-
 pom.xml                                         |  35 ++-
 tests/integration-tests/pom.xml                 |  55 ++++-
 .../integration/karaf/ArtemisFeatureTest.java   | 242 +++++++++++++++++++
 6 files changed, 328 insertions(+), 23 deletions(-)
----------------------------------------------------------------------



[2/2] activemq-artemis git commit: ARTEMIS-521 - OSGi support - add unit test

Posted by jb...@apache.org.
ARTEMIS-521 - OSGi support - add unit test

ARTEMIS-521 - OSGi support - move unit test to integration tests


Project: http://git-wip-us.apache.org/repos/asf/activemq-artemis/repo
Commit: http://git-wip-us.apache.org/repos/asf/activemq-artemis/commit/e994eda3
Tree: http://git-wip-us.apache.org/repos/asf/activemq-artemis/tree/e994eda3
Diff: http://git-wip-us.apache.org/repos/asf/activemq-artemis/diff/e994eda3

Branch: refs/heads/master
Commit: e994eda356c677a979020c280acfeb4f65bf203b
Parents: 6204aaa
Author: Dejan Bosanac <de...@nighttale.net>
Authored: Thu May 19 13:56:00 2016 +0200
Committer: jbertram <jb...@apache.org>
Committed: Thu May 19 11:53:31 2016 -0500

----------------------------------------------------------------------
 artemis-features/pom.xml                        |   1 +
 .../src/main/resources/features.xml             |  16 +-
 docs/user-manual/en/karaf.md                    |   2 +-
 pom.xml                                         |  35 ++-
 tests/integration-tests/pom.xml                 |  55 ++++-
 .../integration/karaf/ArtemisFeatureTest.java   | 242 +++++++++++++++++++
 6 files changed, 328 insertions(+), 23 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/e994eda3/artemis-features/pom.xml
----------------------------------------------------------------------
diff --git a/artemis-features/pom.xml b/artemis-features/pom.xml
index ea07a24..805beb1 100644
--- a/artemis-features/pom.xml
+++ b/artemis-features/pom.xml
@@ -67,6 +67,7 @@
 								<artifact>
 									<file>target/classes/features.xml</file>
 									<type>xml</type>
+									<classifier>features</classifier>
 								</artifact>
 								<artifact>
 									<file>target/classes/artemis.xml</file>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/e994eda3/artemis-features/src/main/resources/features.xml
----------------------------------------------------------------------
diff --git a/artemis-features/src/main/resources/features.xml b/artemis-features/src/main/resources/features.xml
index 82d4cfc..0a88f80 100644
--- a/artemis-features/src/main/resources/features.xml
+++ b/artemis-features/src/main/resources/features.xml
@@ -43,23 +43,23 @@
 		<configfile finalname="etc/artemis.xml">mvn:org.apache.activemq/artemis-features/${pom.version}/xml/artemis</configfile>
 
 		<bundle>mvn:org.apache.geronimo.specs/geronimo-jms_2.0_spec/${geronimo.jms.2.spec.version}</bundle>
-		<bundle>mvn:com.google.guava/guava/18.0</bundle>
+		<bundle>mvn:com.google.guava/guava/${guava.version}</bundle>
 		<bundle>mvn:io.netty/netty-codec-http/${netty.version}</bundle>
-		<bundle>mvn:commons-beanutils/commons-beanutils/1.9.2</bundle>
-		<bundle>mvn:commons-collections/commons-collections/3.2.2</bundle>
+		<bundle>mvn:commons-beanutils/commons-beanutils/${commons.beanutils.version}</bundle>
+		<bundle>mvn:commons-collections/commons-collections/${commons.collections.version}</bundle>
 
-		<bundle>mvn:org.jboss.logging/jboss-logging/3.3.0.Final</bundle>
-		<bundle>mvn:org.jgroups/jgroups/3.6.0.Final</bundle>
+		<bundle>mvn:org.jboss.logging/jboss-logging/${jboss.logging.version}</bundle>
+		<bundle>mvn:org.jgroups/jgroups/${jgroups.version}</bundle>
 
 		<bundle>mvn:org.apache.activemq/artemis-native/${pom.version}</bundle>
 		<bundle>mvn:org.apache.activemq/artemis-server-osgi/${pom.version}</bundle>
 	</feature>
 
 	<feature name="artemis-amqp" version="${pom.version}">
+		<feature prerequisite="true">wrap</feature>
 		<feature>artemis-core</feature>
-		<bundle>mvn:org.apache.servicemix.bundles/org.apache.servicemix.bundles.qpid/0.32_1</bundle>
-		<bundle>wrap:mvn:org.apache.qpid/proton-j/0.10</bundle>
-		<bundle>wrap:mvn:org.apache.qpid/proton-jms/0.10</bundle>
+		<bundle>wrap:mvn:org.apache.qpid/proton-j/${proton.version}</bundle>
+		<bundle>wrap:mvn:org.apache.qpid/qpid-jms-client/${qpid.jms.version}</bundle>
 		<bundle>mvn:org.apache.activemq/artemis-proton-plug/${pom.version}</bundle>
 		<bundle>mvn:org.apache.activemq/artemis-amqp-protocol/${pom.version}</bundle>
 	</feature>

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/e994eda3/docs/user-manual/en/karaf.md
----------------------------------------------------------------------
diff --git a/docs/user-manual/en/karaf.md b/docs/user-manual/en/karaf.md
index 5da4ac7..2b6e8a6 100644
--- a/docs/user-manual/en/karaf.md
+++ b/docs/user-manual/en/karaf.md
@@ -2,6 +2,6 @@
 
 Apache ActiveMQ Artemis can be installed on Apache Karaf (4.x or later) using the following commands from the Karaf shell:
 
-    feature:repo-add mvn:org.apache.activemq/artemis-features/1.3.0-SNAPSHOT/xml
+    feature:repo-add mvn:org.apache.activemq/artemis-features/1.3.0-SNAPSHOT/xml/features
     feature:install artemis
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/e994eda3/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index ed33038..eef50be 100644
--- a/pom.xml
+++ b/pom.xml
@@ -68,10 +68,23 @@
    <properties>
        <!-- base url for site deployment.  See distribution management for full url.  Override this in settings.xml for staging -->
       <staging.siteURL>scp://people.apache.org/x1/www/activemq.apache.org</staging.siteURL>
-      <netty.version>4.0.32.Final</netty.version>
+
+      <activemq5-version>5.12.0</activemq5-version>
+      <apache.derby.version>10.11.1.1</apache.derby.version>
+      <commons.beanutils.version>1.9.2</commons.beanutils.version>
+      <commons.collections.version>3.2.2</commons.collections.version>
+      <fuse.mqtt.client.version>1.10</fuse.mqtt.client.version>
+      <guava.version>18.0</guava.version>
+      <jboss.logging.version>3.3.0.Final</jboss.logging.version>
       <jetty.version>9.2.11.v20150529</jetty.version>
-      <slf4j.version>1.7.12</slf4j.version>
+      <jgroups.version>3.6.8.Final</jgroups.version>
       <maven.assembly.plugin.version>2.4</maven.assembly.plugin.version>
+      <netty.version>4.0.32.Final</netty.version>
+      <proton.version>0.12.1</proton.version>
+      <resteasy.version>3.0.16.Final</resteasy.version>
+      <slf4j.version>1.7.12</slf4j.version>
+      <qpid.jms.version>0.9.0</qpid.jms.version>
+
       <activemq.version.versionName>${project.version}</activemq.version.versionName>
       <activemq.version.majorVersion>1</activemq.version.majorVersion>
       <activemq.version.minorVersion>0</activemq.version.minorVersion>
@@ -81,11 +94,7 @@
       <ActiveMQ-Version>
          ${project.version}(${activemq.version.incrementingVersion})
       </ActiveMQ-Version>
-      <resteasy.version>3.0.16.Final</resteasy.version>
-      <proton.version>0.12.0</proton.version>
-      <activemq5-version>5.12.0</activemq5-version>
-      <fuse.mqtt.client.version>1.10</fuse.mqtt.client.version>
-      <apache.derby.version>10.11.1.1</apache.derby.version>
+
       <skipUnitTests>true</skipUnitTests>
       <skipJmsTests>true</skipJmsTests>
       <skipExtraTests>true</skipExtraTests>
@@ -223,7 +232,7 @@
          <dependency>
             <groupId>commons-collections</groupId>
             <artifactId>commons-collections-testframework</artifactId>
-            <version>3.2.2</version>
+            <version>${commons.collections.version}</version>
             <!-- License: Apache 2.0 -->
          </dependency>
          <!-- ## End Test Dependencies ## -->
@@ -295,13 +304,13 @@
          <dependency>
             <groupId>com.google.guava</groupId>
             <artifactId>guava</artifactId>
-            <version>18.0</version>
+            <version>${guava.version}</version>
             <!-- License: Apache 2.0 -->
          </dependency>
          <dependency>
             <groupId>org.jboss.logging</groupId>
             <artifactId>jboss-logging</artifactId>
-            <version>3.3.0.Final</version>
+            <version>${jboss.logging.version}</version>
             <!-- License: Apache 2.0 -->
          </dependency>
          <dependency>
@@ -326,7 +335,7 @@
          <dependency>
             <groupId>commons-collections</groupId>
             <artifactId>commons-collections</artifactId>
-            <version>3.2.2</version>
+            <version>${commons.collections.version}</version>
             <!-- License: Apache 2.0 -->
          </dependency>
 
@@ -379,7 +388,7 @@
          <dependency>
             <groupId>org.jgroups</groupId>
             <artifactId>jgroups</artifactId>
-            <version>3.6.8.Final</version>
+            <version>${jgroups.version}</version>
             <!-- License: Apache 2.0 -->
          </dependency>
          <dependency>
@@ -527,7 +536,7 @@
          <dependency>
             <groupId>commons-beanutils</groupId>
             <artifactId>commons-beanutils</artifactId>
-            <version>1.9.2</version>
+            <version>${commons.beanutils.version}</version>
             <!-- License: Apache 2.0 -->
          </dependency>
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/e994eda3/tests/integration-tests/pom.xml
----------------------------------------------------------------------
diff --git a/tests/integration-tests/pom.xml b/tests/integration-tests/pom.xml
index 38ac4c2..e3106fc 100644
--- a/tests/integration-tests/pom.xml
+++ b/tests/integration-tests/pom.xml
@@ -28,6 +28,8 @@
 
    <properties>
       <activemq.basedir>${project.basedir}/../..</activemq.basedir>
+      <karaf.version>4.0.3</karaf.version>
+	  <pax.exam.version>4.7.0</pax.exam.version>
       <vertx.version>2.1.2</vertx.version>
       <vertx.testtools.version>2.0.3-final</vertx.testtools.version>
    </properties>
@@ -143,6 +145,12 @@
          <artifactId>artemis-hornetq-protocol</artifactId>
          <version>${project.version}</version>
       </dependency>
+	   <dependency>
+		   <groupId>org.apache.activemq</groupId>
+		   <artifactId>artemis-features</artifactId>
+		   <version>${project.version}</version>
+		   <type>pom</type>
+	   </dependency>
 
       <!-- MQTT Deps -->
       <dependency>
@@ -194,7 +202,7 @@
       <dependency>
          <groupId>org.apache.qpid</groupId>
          <artifactId>qpid-jms-client</artifactId>
-         <version>0.7.0</version>
+         <version>${qpid.jms.version}</version>
       </dependency>
       <dependency>
           <groupId>org.apache.qpid</groupId>
@@ -285,6 +293,38 @@
             </exclusion>
          </exclusions>
       </dependency>
+
+	  <!-- karaf test -->
+
+	   <dependency>
+		   <groupId>org.ops4j.pax.exam</groupId>
+		   <artifactId>pax-exam-container-karaf</artifactId>
+		   <version>${pax.exam.version}</version>
+		   <scope>test</scope>
+	   </dependency>
+	   <dependency>
+		   <groupId>org.ops4j.pax.exam</groupId>
+		   <artifactId>pax-exam-junit4</artifactId>
+		   <version>${pax.exam.version}</version>
+		   <scope>test</scope>
+	   </dependency>
+	   <dependency>
+		   <groupId>org.apache.geronimo.specs</groupId>
+		   <artifactId>geronimo-atinject_1.0_spec</artifactId>
+		   <version>1.0</version>
+		   <scope>provided</scope>
+	   </dependency>
+	   <dependency>
+		   <groupId>org.apache.karaf</groupId>
+		   <artifactId>apache-karaf</artifactId>
+		   <version>${karaf.version}</version>
+		   <type>tar.gz</type>
+	   </dependency>
+	   <dependency>
+		   <groupId>org.apache.karaf.shell</groupId>
+		   <artifactId>org.apache.karaf.shell.console</artifactId>
+		   <version>${karaf.version}</version>
+	   </dependency>
    </dependencies>
 
    <build>
@@ -319,6 +359,19 @@
                <argLine>-Djgroups.bind_addr=::1 ${activemq-surefire-argline}</argLine>
             </configuration>
          </plugin>
+		  <plugin>
+			  <groupId>org.apache.servicemix.tooling</groupId>
+			  <artifactId>depends-maven-plugin</artifactId>
+			  <version>1.2</version>
+			  <executions>
+				  <execution>
+					  <id>generate-depends-file</id>
+					  <goals>
+						  <goal>generate-depends-file</goal>
+					  </goals>
+				  </execution>
+			  </executions>
+		  </plugin>
       </plugins>
    </build>
 

http://git-wip-us.apache.org/repos/asf/activemq-artemis/blob/e994eda3/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/karaf/ArtemisFeatureTest.java
----------------------------------------------------------------------
diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/karaf/ArtemisFeatureTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/karaf/ArtemisFeatureTest.java
new file mode 100644
index 0000000..e7594cc
--- /dev/null
+++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/karaf/ArtemisFeatureTest.java
@@ -0,0 +1,242 @@
+/**
+ * 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.activemq.artemis.tests.integration.karaf;
+
+import org.apache.karaf.jaas.boot.principal.RolePrincipal;
+import org.apache.karaf.jaas.boot.principal.UserPrincipal;
+import org.apache.karaf.shell.api.console.Session;
+import org.apache.karaf.shell.api.console.SessionFactory;
+import org.apache.log4j.Logger;
+import org.apache.qpid.jms.JmsConnectionFactory;
+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.ProbeBuilder;
+import org.ops4j.pax.exam.TestProbeBuilder;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
+import org.ops4j.pax.exam.karaf.options.LogLevelOption;
+import org.ops4j.pax.exam.options.UrlReference;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.util.tracker.ServiceTracker;
+
+import javax.inject.Inject;
+import javax.security.auth.Subject;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.security.PrivilegedAction;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.karafDistributionConfiguration;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel;
+
+@RunWith(PaxExam.class)
+public class ArtemisFeatureTest extends Assert {
+
+   private static Logger LOG = Logger.getLogger(ArtemisFeatureTest.class.getName());
+
+   @Inject
+   BundleContext bundleContext;
+
+   @Inject
+   SessionFactory sessionFactory;
+
+   ExecutorService executor = Executors.newCachedThreadPool();
+
+   public static final long ASSERTION_TIMEOUT = 30000L;
+   public static final long COMMAND_TIMEOUT = 30000L;
+   public static final String USER = "karaf";
+   public static final String PASSWORD = "karaf";
+
+   @ProbeBuilder
+   public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
+      probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*,org.ops4j.pax.exam.options.*,org.apache.felix.service.*;status=provisional");
+      return probe;
+   }
+
+   @Configuration
+   public static Option[] configure() {
+      return configure("artemis");
+   }
+
+   public static Option[] configure(String... features) {
+
+      ArrayList<String> f = new ArrayList<String>();
+      f.addAll(Arrays.asList(features));
+
+      Option[] options =
+            new Option[]{
+                  karafDistributionConfiguration().frameworkUrl(
+                        maven().groupId("org.apache.karaf").artifactId("apache-karaf").type("tar.gz").versionAsInProject())
+                        .unpackDirectory(new File("target/paxexam/unpack/")),
+
+                  KarafDistributionOption.keepRuntimeFolder(),
+                  logLevel(LogLevelOption.LogLevel.INFO),
+                  editConfigurationFilePut("etc/config.properties", "karaf.startlevel.bundle", "50"),
+                  //debugConfiguration("5005", true),
+                  features(getArtemisMQKarafFeatureUrl(), f.toArray(new String[f.size()]))};
+
+      return options;
+   }
+
+   public static UrlReference getArtemisMQKarafFeatureUrl() {
+      String type = "xml/features";
+      UrlReference urlReference = mavenBundle().groupId("org.apache.activemq").
+            artifactId("artemis-features").versionAsInProject().type(type);
+      LOG.info("FeatureURL: " + urlReference.getURL());
+      return urlReference;
+   }
+
+   @Test(timeout = 5 * 60 * 1000)
+   public void test() throws Throwable {
+      executeCommand("bundle:list");
+
+      withinReason(new Callable<Boolean>() {
+         @Override
+         public Boolean call() throws Exception {
+            assertTrue("artemis bundle installed", verifyBundleInstalled("artemis-server-osgi"));
+            return true;
+         }
+      });
+
+      Object service = waitForService("(objectClass=org.apache.activemq.artemis.core.server.ActiveMQServer)", 30000);
+      assertNotNull(service);
+      LOG.info("have service " + service);
+
+      executeCommand("service:list -n");
+
+      String amqpURI = "amqp://localhost:5672";
+      JmsConnectionFactory factory = new JmsConnectionFactory(amqpURI);
+      factory.setUsername(USER);
+      factory.setPassword(PASSWORD);
+
+      //TODO fix security settings and test sending/receiving messages
+        /*
+      Connection connection = factory.createConnection();
+      connection.start();*/
+   }
+
+   protected String executeCommand(final String command, final Long timeout, final Boolean silent) {
+      String response;
+      final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+      final PrintStream printStream = new PrintStream(byteArrayOutputStream);
+      final Session commandSession = sessionFactory.create(System.in, printStream, printStream);
+      commandSession.put("APPLICATION", System.getProperty("karaf.name", "root"));
+      commandSession.put("USER", USER);
+      FutureTask<String> commandFuture = new FutureTask<String>(
+            new Callable<String>() {
+               @Override
+               public String call() {
+
+                  Subject subject = new Subject();
+                  subject.getPrincipals().add(new UserPrincipal("admin"));
+                  subject.getPrincipals().add(new RolePrincipal("admin"));
+                  subject.getPrincipals().add(new RolePrincipal("manager"));
+                  subject.getPrincipals().add(new RolePrincipal("viewer"));
+                  return Subject.doAs(subject, new PrivilegedAction<String>() {
+                     @Override
+                     public String run() {
+                        try {
+                           if (!silent) {
+                              System.out.println(command);
+                              System.out.flush();
+                           }
+                           commandSession.execute(command);
+                        }
+                        catch (Exception e) {
+                           e.printStackTrace(System.err);
+                        }
+                        printStream.flush();
+                        return byteArrayOutputStream.toString();
+                     }
+                  });
+               }
+            });
+
+      try {
+         executor.submit(commandFuture);
+         response = commandFuture.get(timeout, TimeUnit.MILLISECONDS);
+      }
+      catch (Exception e) {
+         e.printStackTrace(System.err);
+         response = "SHELL COMMAND TIMED OUT: ";
+      }
+      LOG.info("Execute: " + command + " - Response:" + response);
+      return response;
+   }
+
+   protected String executeCommand(final String command) {
+      return executeCommand(command, COMMAND_TIMEOUT, false);
+   }
+
+   protected boolean withinReason(Callable<Boolean> callable) throws Throwable {
+      long max = System.currentTimeMillis() + ASSERTION_TIMEOUT;
+      while (true) {
+         try {
+            return callable.call();
+         }
+         catch (Throwable t) {
+            if (System.currentTimeMillis() < max) {
+               TimeUnit.SECONDS.sleep(1);
+               continue;
+            }
+            else {
+               throw t;
+            }
+         }
+      }
+   }
+
+   public boolean verifyBundleInstalled(final String bundleName) throws Exception {
+      boolean found = false;
+      for (Bundle bundle : bundleContext.getBundles()) {
+         LOG.debug("Checking: " + bundle.getSymbolicName());
+         if (bundle.getSymbolicName().contains(bundleName)) {
+            found = true;
+            break;
+         }
+      }
+      return found;
+   }
+
+   protected Object waitForService(String filter, long timeout) throws InvalidSyntaxException, InterruptedException {
+      ServiceTracker<Object, Object> st = new ServiceTracker<Object, Object>(bundleContext, bundleContext.createFilter(filter), null);
+      try {
+         st.open();
+         return st.waitForService(timeout);
+      }
+      finally {
+         st.close();
+      }
+   }
+}