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>