You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by jb...@apache.org on 2017/12/21 08:10:55 UTC

[karaf-cave] 02/02: [KARAF-5108] Add Deployer MBean

This is an automated email from the ASF dual-hosted git repository.

jbonofre pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/karaf-cave.git

commit 92789311c77423da741b429eacab718c28eb5b09
Author: Jean-Baptiste Onofré <jb...@apache.org>
AuthorDate: Wed Dec 20 13:57:18 2017 +0100

    [KARAF-5108] Add Deployer MBean
---
 assembly/src/main/resources/features.xml           |  14 +-
 deployer/management/pom.xml                        |  77 ++++++
 .../deployer/management/CaveDeployerMBean.java     |  67 +++++
 .../deployer/management/internal/Activator.java    |  53 ++++
 .../management/internal/CaveDeployerMBeanImpl.java | 283 +++++++++++++++++++++
 deployer/pom.xml                                   |   1 +
 .../cave/server/management/internal/Activator.java |  21 +-
 7 files changed, 504 insertions(+), 12 deletions(-)

diff --git a/assembly/src/main/resources/features.xml b/assembly/src/main/resources/features.xml
index 82e5529..40a8d87 100644
--- a/assembly/src/main/resources/features.xml
+++ b/assembly/src/main/resources/features.xml
@@ -69,6 +69,7 @@
     <feature name="cave-deployer" version="${project.version}">
         <feature version="${project.version}">cave-deployer-rest</feature>
         <feature version="${project.version}">cave-deployer-command</feature>
+        <feature version="${project.version}">cave-deployer-management</feature>
     </feature>
 
     <feature name="cave-deployer-service" version="${project.version}">
@@ -93,7 +94,18 @@
 
     <feature name="cave-deployer-command" version="${project.version}">
         <feature version="${project.version}">cave-deployer-service</feature>
-        <bundle>mvn:org.apache.karaf.cave.deployer/org.apache.karaf.cave.deployer.command/${project.version}</bundle>
+        <conditional>
+            <condition>shell</condition>
+            <bundle>mvn:org.apache.karaf.cave.deployer/org.apache.karaf.cave.deployer.command/${project.version}</bundle>
+        </conditional>
+    </feature>
+
+    <feature name="cave-deployer-management" version="${project.version}">
+        <feature version="${project.version}">cave-deployer-service</feature>
+        <conditional>
+            <condition>management</condition>
+            <bundle>mvn:org.apache.karaf.cave.deployer/org.apache.karaf.cave.deployer.management/${project.version}</bundle>
+        </conditional>
     </feature>
 
 </features>
\ No newline at end of file
diff --git a/deployer/management/pom.xml b/deployer/management/pom.xml
new file mode 100644
index 0000000..1e11e91
--- /dev/null
+++ b/deployer/management/pom.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+
+    <!--
+
+        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.
+    -->
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.karaf.cave</groupId>
+        <artifactId>org.apache.karaf.cave.deployer</artifactId>
+        <version>4.1.0-SNAPSHOT</version>
+        <relativePath>../pom.xml</relativePath>
+    </parent>
+
+    <groupId>org.apache.karaf.cave.deployer</groupId>
+    <artifactId>org.apache.karaf.cave.deployer.management</artifactId>
+    <packaging>bundle</packaging>
+    <name>Apache Karaf :: Cave :: Deployer :: Management</name>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.cave.deployer</groupId>
+            <artifactId>org.apache.karaf.cave.deployer.api</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>org.apache.karaf.util</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.karaf.tooling</groupId>
+                <artifactId>karaf-services-maven-plugin</artifactId>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <Export-Package>
+                            org.apache.karaf.cave.deployer.management
+                        </Export-Package>
+                        <Private-Package>
+                            org.apache.karaf.cave.server.deployer.internal,
+                            org.apache.karaf.util.tracker*
+                        </Private-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+</project>
\ No newline at end of file
diff --git a/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/CaveDeployerMBean.java b/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/CaveDeployerMBean.java
new file mode 100644
index 0000000..cc573ff
--- /dev/null
+++ b/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/CaveDeployerMBean.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed 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.karaf.cave.deployer.management;
+
+import javax.management.openmbean.TabularData;
+import java.util.List;
+import java.util.Map;
+
+public interface CaveDeployerMBean {
+
+    void registerConnection(String name, String jmxUrl, String karafName, String user, String password) throws Exception;
+    void deleteConnection(String name) throws Exception;
+    TabularData getConnections() throws Exception;
+
+    void explode(String url, String repository) throws Exception;
+    void extract(String url, String directory) throws Exception;
+    void download(String url, String directory) throws Exception;
+    void upload(String groupId, String artifactId, String version, String artifactUrl, String repositoryUrl) throws Exception;
+
+    void assembleFeature(String groupId, String artifactId, String version, String repositoryUrl, String feature,
+                         List<String> repositories, List<String> features, List<String> bundles) throws Exception;
+
+    void installBundle(String url, String connection) throws Exception;
+    void uninstallBundle(String id, String connection) throws Exception;
+    void startBundle(String id, String connection) throws Exception;
+    void stopBundle(String id, String connection) throws Exception;
+    TabularData getBundles(String connection) throws Exception;
+
+    void installKar(String url, String connection) throws Exception;
+    void uninstallKar(String id, String connection) throws Exception;
+    List<String> getKars(String connection) throws Exception;
+
+    void addFeatureRepository(String url, String connection) throws Exception;
+    void removeFeatureRepository(String repository, String connection) throws Exception;
+    TabularData getFeatureRepositories(String connection) throws Exception;
+
+    void installFeature(String feature, String connection) throws Exception;
+    void uninstallFeature(String feature, String connection) throws Exception;
+    TabularData getFeatures(String connection) throws Exception;
+
+    void createConfig(String pid, String connection) throws Exception;
+    Map<String, String> getConfigProperties(String pid, String connection) throws Exception;
+    void deleteConfig(String pid, String connection) throws Exception;
+    void appendConfigProperty(String pid, String key, String value, String connection) throws Exception;
+    void setConfigProperty(String pid, String key, String value, String connection) throws Exception;
+    String getConfigProperty(String pid, String key, String connection) throws Exception;
+    void deleteConfigProperty(String pid, String key, String connection) throws Exception;
+
+    List<String> getClusterNodes(String connection) throws Exception;
+    Map<String, List<String>> getClusterGroups(String connection) throws Exception;
+    void clusterFeatureRepositoryAdd(String url, String clusterGroup, String connection) throws Exception;
+    void clusterFeatureRepositoryRemove(String url, String clusterGroup, String connection) throws Exception;
+    void clusterFeatureInstall(String feature, String clusterGroup, String connection) throws Exception;
+    void clusterFeatureUninstall(String feature, String clusterGroup, String connection) throws Exception;
+
+}
diff --git a/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/internal/Activator.java b/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/internal/Activator.java
new file mode 100644
index 0000000..4daf8a0
--- /dev/null
+++ b/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/internal/Activator.java
@@ -0,0 +1,53 @@
+/*
+ * Licensed 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.karaf.cave.deployer.management.internal;
+
+import org.apache.karaf.cave.deployer.api.Deployer;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.apache.karaf.util.tracker.annotation.RequireService;
+import org.apache.karaf.util.tracker.annotation.Services;
+import org.osgi.framework.ServiceRegistration;
+
+import java.util.Hashtable;
+
+@Services(
+        requires = {
+                @RequireService(Deployer.class)
+        }
+)
+public class Activator extends BaseActivator {
+
+    private volatile ServiceRegistration mbeanRegistration;
+
+    @Override
+    protected void doStart() throws Exception {
+        Deployer deployer = getTrackedService(Deployer.class);
+        CaveDeployerMBeanImpl mbean = new CaveDeployerMBeanImpl();
+        mbean.setDeployer(deployer);
+
+        Hashtable<String, Object> props = new Hashtable<>();
+        props.put("jmx.objectname", "org.apache.karaf.cave:type=deployer,name=" + System.getProperty("karaf.name"));
+        mbeanRegistration = this.bundleContext.registerService(getInterfaceNames(mbean), mbean, props);
+    }
+
+    @Override
+    protected void doStop() {
+        if (mbeanRegistration != null) {
+            mbeanRegistration.unregister();
+            mbeanRegistration = null;
+        }
+        super.doStop();
+    }
+
+}
diff --git a/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/internal/CaveDeployerMBeanImpl.java b/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/internal/CaveDeployerMBeanImpl.java
new file mode 100644
index 0000000..2fa006b
--- /dev/null
+++ b/deployer/management/src/main/java/org/apache/karaf/cave/deployer/management/internal/CaveDeployerMBeanImpl.java
@@ -0,0 +1,283 @@
+/*
+ * Licensed 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.karaf.cave.deployer.management.internal;
+
+import org.apache.karaf.cave.deployer.api.*;
+import org.apache.karaf.cave.deployer.management.CaveDeployerMBean;
+
+import javax.management.NotCompliantMBeanException;
+import javax.management.StandardMBean;
+import javax.management.openmbean.*;
+import java.util.List;
+import java.util.Map;
+
+public class CaveDeployerMBeanImpl extends StandardMBean implements CaveDeployerMBean {
+
+    private Deployer deployer;
+
+    public CaveDeployerMBeanImpl() throws NotCompliantMBeanException {
+        super(CaveDeployerMBean.class);
+    }
+
+    public Deployer getDeployer() {
+        return deployer;
+    }
+
+    public void setDeployer(Deployer deployer) {
+        this.deployer = deployer;
+    }
+
+
+    @Override
+    public void registerConnection(String name, String jmxUrl, String karafName, String user, String password) throws Exception {
+        Connection connection = new Connection();
+        connection.setName(name);
+        connection.setJmxUrl(jmxUrl);
+        connection.setKarafName(karafName);
+        connection.setUser(user);
+        connection.setPassword(password);
+        deployer.registerConnection(connection);
+    }
+
+    @Override
+    public void deleteConnection(String name) throws Exception {
+        deployer.deleteConnection(name);
+    }
+
+    @Override
+    public TabularData getConnections() throws Exception {
+        List<Connection> connections = deployer.connections();
+
+        CompositeType connectionType = new CompositeType("Connection", "Connection to a Karaf instance",
+                new String[]{"Name", "JMX URL", "Karaf Name", "User", "Password"},
+                new String[]{"Name of the connection", "JMX URL of the Karaf instance", "Karaf instance name", "Username to connect", "Password of the user" },
+                new OpenType[]{SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.STRING});
+        TabularType tabularType = new TabularType("Connections", "Table of all Cave Deployer connections", connectionType, new String[]{"Name"});
+        TabularData table = new TabularDataSupport(tabularType);
+        for (Connection connection : connections) {
+            CompositeData data = new CompositeDataSupport(connectionType,
+                    new String[]{"Name", "JMX URL", "Karaf Name", "User", "Password"},
+                    new Object[]{connection.getName(), connection.getJmxUrl(), connection.getKarafName(), connection.getUser(), connection.getPassword()});
+            table.put(data);
+        }
+        return table;
+    }
+
+    @Override
+    public void explode(String url, String repository) throws Exception {
+        deployer.explode(url, repository);
+    }
+
+    @Override
+    public void extract(String url, String directory) throws Exception {
+        deployer.extract(url, directory);
+    }
+
+    @Override
+    public void download(String url, String directory) throws Exception {
+        deployer.download(url, directory);
+    }
+
+    @Override
+    public void upload(String groupId, String artifactId, String version, String artifactUrl, String repositoryUrl) throws Exception {
+        deployer.upload(groupId, artifactId, version, artifactUrl, repositoryUrl);
+    }
+
+    @Override
+    public void assembleFeature(String groupId, String artifactId, String version, String repositoryUrl, String feature, List<String> repositories, List<String> features, List<String> bundles) throws Exception {
+        deployer.assembleFeature(groupId, artifactId, version, repositoryUrl, feature, repositories, features, bundles, null);
+    }
+
+    @Override
+    public void installBundle(String url, String connection) throws Exception {
+        deployer.installBundle(url, connection);
+    }
+
+    @Override
+    public void uninstallBundle(String id, String connection) throws Exception {
+        deployer.uninstallBundle(id, connection);
+    }
+
+    @Override
+    public void startBundle(String id, String connection) throws Exception {
+        deployer.startBundle(id, connection);
+    }
+
+    @Override
+    public void stopBundle(String id, String connection) throws Exception {
+        deployer.stopBundle(id, connection);
+    }
+
+    @Override
+    public TabularData getBundles(String connection) throws Exception {
+        CompositeType bundleType = new CompositeType("Bundle", "A bundle on the remote instance",
+                new String[]{"ID", "Name", "Version", "Start Level", "State"},
+                new String[]{"Bundle ID", "Bundle Name", "Bundle Version", "Bundle Start Level", "Bundle State"},
+                new OpenType[]{SimpleType.STRING, SimpleType.STRING, SimpleType.STRING, SimpleType.INTEGER, SimpleType.STRING});
+        TabularType tableType = new TabularType("Bundles", "Table of bundles", bundleType, new String[]{"ID"});
+        TabularData table = new TabularDataSupport(tableType);
+
+        List<Bundle> bundles = deployer.bundles(connection);
+
+        for (Bundle bundle : bundles) {
+            CompositeData data = new CompositeDataSupport(bundleType,
+                    new String[]{"ID", "Name", "Version", "Start Level", "State"},
+                    new Object[]{bundle.getId(), bundle.getName(), bundle.getVersion(), bundle.getStartLevel(), bundle.getState()});
+            table.put(data);
+        }
+
+        return table;
+    }
+
+    @Override
+    public void installKar(String url, String connection) throws Exception {
+        deployer.installKar(url, connection);
+    }
+
+    @Override
+    public void uninstallKar(String id, String connection) throws Exception {
+        deployer.uninstallKar(id, connection);
+    }
+
+    @Override
+    public List<String> getKars(String connection) throws Exception {
+        return deployer.kars(connection);
+    }
+
+    @Override
+    public void addFeatureRepository(String url, String connection) throws Exception {
+        deployer.addFeaturesRepository(url, connection);
+    }
+
+    @Override
+    public void removeFeatureRepository(String repository, String connection) throws Exception {
+        deployer.removeFeaturesRepository(repository, connection);
+    }
+
+    @Override
+    public TabularData getFeatureRepositories(String connection) throws Exception {
+        List<FeaturesRepository> repositories = deployer.featuresRepositories(connection);
+
+        CompositeType repositoryType = new CompositeType("Features Repository", "Features Repository",
+                new String[]{"Name", "URL"},
+                new String[]{"The features repository name", "The location of the features repository"},
+                new OpenType[]{SimpleType.STRING, SimpleType.STRING});
+        TabularType tableType = new TabularType("Features Repositories", "Table of features repositories", repositoryType, new String[]{"Name"});
+        TabularData table = new TabularDataSupport(tableType);
+
+        for (FeaturesRepository repository : repositories) {
+            CompositeData data = new CompositeDataSupport(repositoryType,
+                    new String[]{"Name", "URL"},
+                    new Object[]{repository.getName(), repository.getUri()});
+            table.put(data);
+        }
+        return table;
+    }
+
+    @Override
+    public void installFeature(String feature, String connection) throws Exception {
+        deployer.installFeature(feature, connection);
+    }
+
+    @Override
+    public void uninstallFeature(String feature, String connection) throws Exception {
+        deployer.uninstallFeature(feature, connection);
+    }
+
+    @Override
+    public TabularData getFeatures(String connection) throws Exception {
+        List<Feature> features = deployer.features(connection);
+
+        CompositeType featureType = new CompositeType("Feature", "Feature",
+                new String[]{"Name", "Version", "State"},
+                new String[]{"Name of the feature", "Version of the feature", "State of the feature"},
+                new OpenType[]{SimpleType.STRING, SimpleType.STRING, SimpleType.STRING});
+        TabularType tableType = new TabularType("Features", "Table of features",
+                featureType, new String[]{"Name", "Version"});
+        TabularData table = new TabularDataSupport(tableType);
+        for (Feature feature : features) {
+            CompositeData data = new CompositeDataSupport(featureType,
+                    new String[]{"Name", "Version", "State"},
+                    new Object[]{feature.getName(), feature.getVersion(), feature.getState()});
+            table.put(data);
+        }
+
+        return table;
+    }
+
+    @Override
+    public void createConfig(String pid, String connection) throws Exception {
+        deployer.createConfig(pid, connection);
+    }
+
+    @Override
+    public Map<String, String> getConfigProperties(String pid, String connection) throws Exception {
+        return deployer.configProperties(pid, connection);
+    }
+
+    @Override
+    public void deleteConfig(String pid, String connection) throws Exception {
+        deployer.deleteConfig(pid, connection);
+    }
+
+    @Override
+    public void appendConfigProperty(String pid, String key, String value, String connection) throws Exception {
+        deployer.appendConfigProperty(pid, key, value, connection);
+    }
+
+    @Override
+    public void setConfigProperty(String pid, String key, String value, String connection) throws Exception {
+        deployer.setConfigProperty(pid, key, value, connection);
+    }
+
+    @Override
+    public String getConfigProperty(String pid, String key, String connection) throws Exception {
+        return deployer.configProperty(pid, key, connection);
+    }
+
+    @Override
+    public void deleteConfigProperty(String pid, String key, String connection) throws Exception {
+        deployer.deleteConfigProperty(pid, key, connection);
+    }
+
+    @Override
+    public List<String> getClusterNodes(String connection) throws Exception {
+        return deployer.clusterNodes(connection);
+    }
+
+    @Override
+    public Map<String, List<String>> getClusterGroups(String connection) throws Exception {
+        return deployer.clusterGroups(connection);
+    }
+
+    @Override
+    public void clusterFeatureRepositoryAdd(String url, String clusterGroup, String connection) throws Exception {
+        deployer.clusterAddFeaturesRepository(url, clusterGroup, connection);
+    }
+
+    @Override
+    public void clusterFeatureRepositoryRemove(String url, String clusterGroup, String connection) throws Exception {
+        deployer.clusterRemoveFeaturesRepository(url, clusterGroup, connection);
+    }
+
+    @Override
+    public void clusterFeatureInstall(String feature, String clusterGroup, String connection) throws Exception {
+        deployer.clusterFeatureInstall(feature, clusterGroup, connection);
+    }
+
+    @Override
+    public void clusterFeatureUninstall(String feature, String clusterGroup, String connection) throws Exception {
+        deployer.clusterFeatureUninstall(feature, clusterGroup, connection);
+    }
+}
diff --git a/deployer/pom.xml b/deployer/pom.xml
index 9663f47..976cc09 100644
--- a/deployer/pom.xml
+++ b/deployer/pom.xml
@@ -37,6 +37,7 @@
         <module>api</module>
         <module>service</module>
         <module>command</module>
+        <module>management</module>
         <module>rest</module>
     </modules>
 
diff --git a/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/Activator.java b/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/Activator.java
index 7579caa..092b2f5 100644
--- a/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/Activator.java
+++ b/server/management/src/main/java/org/apache/karaf/cave/server/management/internal/Activator.java
@@ -1,14 +1,3 @@
-package org.apache.karaf.cave.server.management.internal;
-
-import java.util.Hashtable;
-
-import org.apache.karaf.cave.server.api.CaveFeatureGateway;
-import org.apache.karaf.cave.server.api.CaveRepositoryService;
-import org.apache.karaf.util.tracker.BaseActivator;
-import org.apache.karaf.util.tracker.annotation.RequireService;
-import org.apache.karaf.util.tracker.annotation.Services;
-import org.osgi.framework.ServiceRegistration;
-
 /*
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -22,6 +11,16 @@ import org.osgi.framework.ServiceRegistration;
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
+package org.apache.karaf.cave.server.management.internal;
+
+import java.util.Hashtable;
+
+import org.apache.karaf.cave.server.api.CaveFeatureGateway;
+import org.apache.karaf.cave.server.api.CaveRepositoryService;
+import org.apache.karaf.util.tracker.BaseActivator;
+import org.apache.karaf.util.tracker.annotation.RequireService;
+import org.apache.karaf.util.tracker.annotation.Services;
+import org.osgi.framework.ServiceRegistration;
 
 @Services(
         requires = {

-- 
To stop receiving notification emails like this one, please contact
"commits@karaf.apache.org" <co...@karaf.apache.org>.