You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by cs...@apache.org on 2014/02/15 15:59:51 UTC

git commit: KARAF-2762 First version of action/command exporter

Repository: karaf
Updated Branches:
  refs/heads/master 40140e4f0 -> dcaba5edd


KARAF-2762 First version of action/command exporter


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

Branch: refs/heads/master
Commit: dcaba5edd8f05c7b384ce96420ac9b7151d3b174
Parents: 40140e4
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Sat Feb 15 15:59:43 2014 +0100
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Sat Feb 15 15:59:43 2014 +0100

----------------------------------------------------------------------
 shell/command-exporter/pom.xml                  |  86 ++++++++++++
 .../apache/karaf/shell/exporter/Activator.java  |  62 +++++++++
 .../karaf/shell/exporter/CommandExporter.java   | 131 +++++++++++++++++++
 shell/pom.xml                                   |   1 +
 4 files changed, 280 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/dcaba5ed/shell/command-exporter/pom.xml
----------------------------------------------------------------------
diff --git a/shell/command-exporter/pom.xml b/shell/command-exporter/pom.xml
new file mode 100644
index 0000000..c756b5d
--- /dev/null
+++ b/shell/command-exporter/pom.xml
@@ -0,0 +1,86 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.karaf.shell</groupId>
+    <artifactId>shell</artifactId>
+    <version>3.0.1-SNAPSHOT</version>
+  </parent>
+  <artifactId>command-exporter</artifactId>
+  <packaging>bundle</packaging>
+  
+      <properties>
+        <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.console</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.shell</groupId>
+            <artifactId>org.apache.karaf.shell.table</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf.package</groupId>
+            <artifactId>org.apache.karaf.package.core</artifactId>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.gogo.runtime</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-jdk14</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.utils</artifactId>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <resources>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <includes>
+                    <include>**/*</include>
+                </includes>
+            </resource>
+            <resource>
+                <directory>${project.basedir}/src/main/resources</directory>
+                <filtering>true</filtering>
+                <includes>
+                    <include>**/*.info</include>
+                </includes>
+            </resource>
+        </resources>
+        <plugins>
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                    	<Bundle-Activator>org.apache.karaf.shell.exporter.Activator</Bundle-Activator>
+                        <Export-Package>!*</Export-Package>
+                    </instructions>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/dcaba5ed/shell/command-exporter/src/main/java/org/apache/karaf/shell/exporter/Activator.java
----------------------------------------------------------------------
diff --git a/shell/command-exporter/src/main/java/org/apache/karaf/shell/exporter/Activator.java b/shell/command-exporter/src/main/java/org/apache/karaf/shell/exporter/Activator.java
new file mode 100644
index 0000000..8ce28f4
--- /dev/null
+++ b/shell/command-exporter/src/main/java/org/apache/karaf/shell/exporter/Activator.java
@@ -0,0 +1,62 @@
+/*
+ * 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.shell.exporter;
+
+import org.apache.felix.gogo.commands.Action;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SuppressWarnings("deprecation")
+public class Activator implements BundleActivator {
+    Logger logger = LoggerFactory.getLogger(this.getClass());
+    
+    @Override
+    public void start(BundleContext context) throws Exception {
+        ServiceTracker<Action, Action> tracker = new ServiceTracker<Action, Action>(context, Action.class, null) {
+
+            @Override
+            public Action addingService(ServiceReference<Action> reference) {
+                Bundle userBundle = reference.getBundle();
+                try {
+                    Action action = context.getService(reference);
+                    CommandExporter.export(userBundle.getBundleContext(), action);
+                    logger.info("Service registered");
+                } catch (Exception e) {
+                    logger.warn("Error exporting action from service of bundle " 
+                        + userBundle.getSymbolicName()
+                        + "[" + userBundle.getBundleId() + "]", e);
+                }
+                return super.addingService(reference);
+            }
+
+            @Override
+            public void removedService(ServiceReference<Action> reference, Action service) {
+                // TODO implement removing of commands
+                super.removedService(reference, service);
+            }
+            
+        };
+        tracker.open();
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/dcaba5ed/shell/command-exporter/src/main/java/org/apache/karaf/shell/exporter/CommandExporter.java
----------------------------------------------------------------------
diff --git a/shell/command-exporter/src/main/java/org/apache/karaf/shell/exporter/CommandExporter.java b/shell/command-exporter/src/main/java/org/apache/karaf/shell/exporter/CommandExporter.java
new file mode 100644
index 0000000..a9c75c3
--- /dev/null
+++ b/shell/command-exporter/src/main/java/org/apache/karaf/shell/exporter/CommandExporter.java
@@ -0,0 +1,131 @@
+/*
+ * 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.karaf.shell.exporter;
+
+import java.lang.reflect.Field;
+import java.util.ArrayList;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.felix.gogo.commands.Action;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.CommandWithAction;
+import org.apache.felix.gogo.commands.basic.AbstractCommand;
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.Function;
+import org.apache.karaf.shell.console.CompletableFunction;
+import org.apache.karaf.shell.console.Completer;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Exports an Action as a command using a template for the action injects
+ */
+@SuppressWarnings("deprecation")
+public class CommandExporter extends AbstractCommand implements CompletableFunction {
+    private static Logger logger = LoggerFactory.getLogger(CommandExporter.class);
+
+    private Action actionTemplate;
+    private List<Completer> completers = new ArrayList<Completer>();
+
+    public CommandExporter(Action actionTemplate)
+    {
+        this.actionTemplate = actionTemplate;
+        addCompleters();
+    }
+
+    public Class<? extends Action> getActionClass()
+    {
+        return actionTemplate.getClass();
+    }
+
+    public Action createNewAction() {
+        try {
+            Action newAction = actionTemplate.getClass().newInstance();
+            copyFields(newAction);
+            return newAction;
+        } catch (InstantiationException e) {
+            throw new RuntimeException(e);
+        } catch (IllegalAccessException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private void copyFields(Action newAction) {
+        Field[] fields = actionTemplate.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            try {
+                field.setAccessible(true);
+                Object value = field.get(actionTemplate);
+                field.set(newAction, value);
+            } catch (Exception e) {
+                throw new RuntimeException(e.getMessage(), e);
+            }
+        }
+    }
+
+    @SuppressWarnings("rawtypes")
+    public static ServiceRegistration export(BundleContext context, Action actionTemplate)
+    {
+        Class<? extends Action> actionClass = actionTemplate.getClass();
+        logger.info(actionClass.getName());
+        Command cmd = actionClass.getAnnotation(Command.class);
+        if (cmd == null)
+        {
+            throw new IllegalArgumentException("Action class is not annotated with @Command");
+        }
+        Hashtable<String, String> props = new Hashtable<String, String>();
+        props.put(CommandProcessor.COMMAND_SCOPE, cmd.scope());
+        props.put(CommandProcessor.COMMAND_FUNCTION, cmd.name());
+        CommandExporter command = new CommandExporter(actionTemplate);
+        return context.registerService(new String[]{
+                                                    Function.class.getName(),
+                                                    CommandWithAction.class.getName(),
+                                                    AbstractCommand.class.getName()
+                                                    }, 
+                                       command, props);
+    }
+
+    private void addCompleters() {
+        for (Field field : actionTemplate.getClass().getDeclaredFields()) {
+            field.setAccessible(true);
+            if (Completer.class.isAssignableFrom(field.getType())) {
+                try {
+                    this.completers.add((Completer)field.get(actionTemplate));
+                } catch (Exception e) {
+                    logger.warn("Error setting completer from field " + field.getName());
+                }
+            }
+        }
+    }
+
+    @Override
+    public List<Completer> getCompleters() {
+        return completers;
+    }
+
+    @Override
+    public Map<String, Completer> getOptionalCompleters() {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/dcaba5ed/shell/pom.xml
----------------------------------------------------------------------
diff --git a/shell/pom.xml b/shell/pom.xml
index 7367691..7cd53a0 100644
--- a/shell/pom.xml
+++ b/shell/pom.xml
@@ -39,6 +39,7 @@
         <module>ssh</module>
         <module>help</module>
         <module>table</module>
+        <module>command-exporter</module>
     </modules>
 
 </project>