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/24 11:28:09 UTC
[11/11] git commit: KARAF-2772 Extracting command-api
KARAF-2772 Extracting command-api
Project: http://git-wip-us.apache.org/repos/asf/karaf/repo
Commit: http://git-wip-us.apache.org/repos/asf/karaf/commit/1ee78df9
Tree: http://git-wip-us.apache.org/repos/asf/karaf/tree/1ee78df9
Diff: http://git-wip-us.apache.org/repos/asf/karaf/diff/1ee78df9
Branch: refs/heads/command-api
Commit: 1ee78df92a1345d2236c0000d22962d69324b787
Parents: 6fdb03b
Author: Christian Schneider <ch...@die-schneider.net>
Authored: Mon Feb 24 11:27:32 2014 +0100
Committer: Christian Schneider <ch...@die-schneider.net>
Committed: Mon Feb 24 11:27:32 2014 +0100
----------------------------------------------------------------------
jaas/modules/pom.xml | 1 +
pom.xml | 5 +
shell/command-api/NOTICE | 71 +++
shell/command-api/pom.xml | 131 +++++
.../karaf/shell/console/branding-ssh.properties | 34 ++
.../karaf/shell/console/branding.properties | 33 ++
.../org/apache/felix/gogo/commands/Action.java | 29 +
.../apache/felix/gogo/commands/Argument.java | 49 ++
.../org/apache/felix/gogo/commands/Command.java | 53 ++
.../felix/gogo/commands/CommandException.java | 63 +++
.../felix/gogo/commands/CommandWithAction.java | 32 ++
.../felix/gogo/commands/CompleterValues.java | 37 ++
.../org/apache/felix/gogo/commands/Option.java | 48 ++
.../apache/felix/gogo/commands/SubShell.java | 46 ++
.../gogo/commands/basic/AbstractCommand.java | 64 +++
.../gogo/commands/basic/ActionPreparator.java | 31 +
.../commands/basic/DefaultActionPreparator.java | 566 ++++++++++++++++++
.../commands/converter/DefaultConverter.java | 402 +++++++++++++
.../gogo/commands/converter/GenericType.java | 196 +++++++
.../gogo/commands/converter/ReifiedType.java | 118 ++++
.../org/apache/karaf/shell/commands/Action.java | 40 ++
.../apache/karaf/shell/commands/Argument.java | 48 ++
.../apache/karaf/shell/commands/Command.java | 53 ++
.../karaf/shell/commands/CommandException.java | 64 +++
.../karaf/shell/commands/CommandWithAction.java | 31 +
.../apache/karaf/shell/commands/Completer.java | 34 ++
.../karaf/shell/commands/CompleterValues.java | 37 ++
.../apache/karaf/shell/commands/HelpOption.java | 54 ++
.../karaf/shell/commands/InfoProvider.java | 30 +
.../org/apache/karaf/shell/commands/Option.java | 46 ++
.../karaf/shell/commands/ansi/SimpleAnsi.java | 28 +
.../shell/commands/basic/AbstractCommand.java | 62 ++
.../shell/commands/basic/ActionPreparator.java | 42 ++
.../commands/basic/DefaultActionPreparator.java | 223 ++++++++
.../shell/commands/basic/SimpleCommand.java | 82 +++
.../commands/converter/DefaultConverter.java | 401 +++++++++++++
.../shell/commands/converter/GenericType.java | 195 +++++++
.../shell/commands/converter/ReifiedType.java | 116 ++++
.../shell/commands/meta/ActionMetaData.java | 296 ++++++++++
.../commands/meta/ActionMetaDataFactory.java | 251 ++++++++
.../karaf/shell/console/AbstractAction.java | 50 ++
.../shell/console/BlueprintContainerAware.java | 27 +
.../karaf/shell/console/BundleContextAware.java | 27 +
.../shell/console/CloseShellException.java | 27 +
.../shell/console/CommandSessionHolder.java | 38 ++
.../shell/console/CompletableFunction.java | 31 +
.../apache/karaf/shell/console/Completer.java | 27 +
.../org/apache/karaf/shell/console/Console.java | 29 +
.../apache/karaf/shell/console/ExitAction.java | 46 ++
.../karaf/shell/console/HelpProvider.java | 26 +
.../karaf/shell/console/MultiException.java | 95 ++++
.../apache/karaf/shell/console/NameScoping.java | 79 +++
.../karaf/shell/console/OsgiCommandSupport.java | 103 ++++
.../karaf/shell/console/SessionProperties.java | 28 +
.../apache/karaf/shell/console/SubShell.java | 38 ++
.../karaf/shell/console/SubShellAction.java | 39 ++
.../console/commands/AnnotatedSubShell.java | 43 ++
.../shell/console/commands/BasicSubShell.java | 51 ++
.../console/commands/BlueprintCommand.java | 110 ++++
.../shell/console/commands/GenericType.java | 195 +++++++
.../console/commands/NamespaceHandler.java | 523 +++++++++++++++++
.../commands/NumberToStringConverter.java | 36 ++
.../console/completer/AggregateCompleter.java | 91 +++
.../console/completer/ArgumentCompleter.java | 567 +++++++++++++++++++
.../completer/CommandNamesCompleter.java | 103 ++++
.../console/completer/CommandsCompleter.java | 321 +++++++++++
.../shell/console/completer/FileCompleter.java | 147 +++++
.../shell/console/completer/NullCompleter.java | 32 ++
.../console/completer/OldArgumentCompleter.java | 448 +++++++++++++++
.../karaf/shell/console/completer/Parser.java | 396 +++++++++++++
.../console/completer/StringsCompleter.java | 103 ++++
.../org/apache/karaf/shell/inject/Destroy.java | 29 +
.../org/apache/karaf/shell/inject/Init.java | 29 +
.../apache/karaf/shell/inject/Reference.java | 29 +
.../org/apache/karaf/shell/inject/Service.java | 29 +
.../blueprint/shell-namespacehandler.xml | 42 ++
.../src/main/resources/OSGI-INF/bundle.info | 14 +
.../console/commands/karaf-shell-1.0.0.xsd | 217 +++++++
.../console/commands/karaf-shell-1.1.0.xsd | 209 +++++++
.../console/commands/karaf-shell-1.2.0.xsd | 225 ++++++++
.../karaf/shell/commands/basic/Context.java | 67 +++
.../shell/commands/basic/SimpleSubShell.java | 39 ++
.../shell/commands/basic/TestCommands.java | 184 ++++++
.../shell/commands/meta/TestFormatting.java | 35 ++
.../completer/ArgumentCompleterTest.java | 145 +++++
.../console/completer/BooleanCompleterTest.java | 62 ++
.../console/completer/CompleterTestSupport.java | 34 ++
.../console/completer/CompleterValuesTest.java | 74 +++
.../shell/console/completer/CompletionTest.java | 172 ++++++
.../console/completer/DummyCommandSession.java | 48 ++
.../console/completer/FileCompleterTest.java | 56 ++
shell/commands/pom.xml | 2 +-
shell/console/pom.xml | 15 +-
.../org/apache/felix/gogo/commands/Action.java | 29 -
.../apache/felix/gogo/commands/Argument.java | 49 --
.../org/apache/felix/gogo/commands/Command.java | 53 --
.../felix/gogo/commands/CommandException.java | 63 ---
.../felix/gogo/commands/CommandWithAction.java | 32 --
.../felix/gogo/commands/CompleterValues.java | 37 --
.../org/apache/felix/gogo/commands/Option.java | 48 --
.../apache/felix/gogo/commands/SubShell.java | 46 --
.../gogo/commands/basic/AbstractCommand.java | 64 ---
.../gogo/commands/basic/ActionPreparator.java | 31 -
.../commands/basic/DefaultActionPreparator.java | 566 ------------------
.../commands/converter/DefaultConverter.java | 402 -------------
.../gogo/commands/converter/GenericType.java | 196 -------
.../gogo/commands/converter/ReifiedType.java | 118 ----
.../org/apache/karaf/shell/commands/Action.java | 40 --
.../apache/karaf/shell/commands/Argument.java | 48 --
.../apache/karaf/shell/commands/Command.java | 53 --
.../karaf/shell/commands/CommandException.java | 64 ---
.../karaf/shell/commands/CommandWithAction.java | 31 -
.../apache/karaf/shell/commands/Completer.java | 34 --
.../karaf/shell/commands/CompleterValues.java | 37 --
.../apache/karaf/shell/commands/HelpOption.java | 54 --
.../karaf/shell/commands/InfoProvider.java | 30 -
.../org/apache/karaf/shell/commands/Option.java | 46 --
.../karaf/shell/commands/ansi/SimpleAnsi.java | 30 -
.../shell/commands/basic/AbstractCommand.java | 62 --
.../shell/commands/basic/ActionPreparator.java | 42 --
.../commands/basic/DefaultActionPreparator.java | 223 --------
.../shell/commands/basic/SimpleCommand.java | 82 ---
.../commands/converter/DefaultConverter.java | 401 -------------
.../shell/commands/converter/GenericType.java | 195 -------
.../shell/commands/converter/ReifiedType.java | 116 ----
.../shell/commands/meta/ActionMetaData.java | 296 ----------
.../commands/meta/ActionMetaDataFactory.java | 251 --------
.../karaf/shell/console/AbstractAction.java | 50 --
.../shell/console/BlueprintContainerAware.java | 27 -
.../karaf/shell/console/BundleContextAware.java | 27 -
.../shell/console/CloseShellException.java | 27 -
.../shell/console/CommandSessionHolder.java | 38 --
.../shell/console/CompletableFunction.java | 31 -
.../apache/karaf/shell/console/Completer.java | 27 -
.../org/apache/karaf/shell/console/Console.java | 29 -
.../apache/karaf/shell/console/ExitAction.java | 46 --
.../karaf/shell/console/HelpProvider.java | 26 -
.../karaf/shell/console/MultiException.java | 95 ----
.../apache/karaf/shell/console/NameScoping.java | 79 ---
.../karaf/shell/console/OsgiCommandSupport.java | 103 ----
.../karaf/shell/console/SessionProperties.java | 28 -
.../apache/karaf/shell/console/SubShell.java | 38 --
.../karaf/shell/console/SubShellAction.java | 39 --
.../console/commands/AnnotatedSubShell.java | 43 --
.../shell/console/commands/BasicSubShell.java | 51 --
.../console/commands/BlueprintCommand.java | 110 ----
.../shell/console/commands/GenericType.java | 195 -------
.../console/commands/NamespaceHandler.java | 523 -----------------
.../commands/NumberToStringConverter.java | 36 --
.../console/completer/AggregateCompleter.java | 91 ---
.../console/completer/ArgumentCompleter.java | 567 -------------------
.../completer/CommandNamesCompleter.java | 103 ----
.../console/completer/CommandsCompleter.java | 321 -----------
.../shell/console/completer/FileCompleter.java | 147 -----
.../shell/console/completer/NullCompleter.java | 32 --
.../console/completer/OldArgumentCompleter.java | 448 ---------------
.../karaf/shell/console/completer/Parser.java | 396 -------------
.../console/completer/StringsCompleter.java | 103 ----
.../org/apache/karaf/shell/inject/Destroy.java | 29 -
.../org/apache/karaf/shell/inject/Init.java | 29 -
.../apache/karaf/shell/inject/Reference.java | 29 -
.../org/apache/karaf/shell/inject/Service.java | 29 -
.../karaf/shell/commands/basic/Context.java | 67 ---
.../shell/commands/basic/SimpleSubShell.java | 39 --
.../shell/commands/basic/TestCommands.java | 184 ------
.../shell/commands/meta/TestFormatting.java | 35 --
.../completer/ArgumentCompleterTest.java | 145 -----
.../console/completer/BooleanCompleterTest.java | 62 --
.../console/completer/CompleterTestSupport.java | 34 --
.../console/completer/CompleterValuesTest.java | 74 ---
.../shell/console/completer/CompletionTest.java | 172 ------
.../console/completer/DummyCommandSession.java | 48 --
.../console/completer/FileCompleterTest.java | 56 --
shell/help/pom.xml | 7 +-
.../help/impl/CommandListHelpProvider.java | 15 +-
shell/pom.xml | 1 +
176 files changed, 9772 insertions(+), 8802 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/jaas/modules/pom.xml
----------------------------------------------------------------------
diff --git a/jaas/modules/pom.xml b/jaas/modules/pom.xml
index a74adc2..908674e 100644
--- a/jaas/modules/pom.xml
+++ b/jaas/modules/pom.xml
@@ -57,6 +57,7 @@
<dependency>
<groupId>org.apache.felix</groupId>
<artifactId>org.apache.felix.fileinstall</artifactId>
+ <scope>provided</scope>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 1b5d4e9..d80d27c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -636,6 +636,11 @@
<dependency>
<groupId>org.apache.karaf.shell</groupId>
+ <artifactId>org.apache.karaf.shell.command.api</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.karaf.shell</groupId>
<artifactId>org.apache.karaf.shell.console</artifactId>
<version>${project.version}</version>
</dependency>
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/NOTICE
----------------------------------------------------------------------
diff --git a/shell/command-api/NOTICE b/shell/command-api/NOTICE
new file mode 100644
index 0000000..de8d101
--- /dev/null
+++ b/shell/command-api/NOTICE
@@ -0,0 +1,71 @@
+Apache Karaf
+Copyright 2010-2013 The Apache Software Foundation
+
+
+I. Included Software
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+The OSGi Alliance (http://www.osgi.org/).
+Copyright (c) OSGi Alliance (2000, 2010).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+OW2 (http://www.ow2.org/).
+Licensed under the BSD License.
+
+This product includes software developed at
+OPS4J (http://www.ops4j.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software developed at
+Eclipse Foundation (http://www.eclipse.org/).
+Licensed under the EPL.
+
+This product includes software written by
+Antony Lesuisse.
+Licensed under Public Domain.
+
+
+II. Used Software
+
+This product uses software developed at
+FUSE Source (http://www.fusesource.org/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+AOP Alliance (http://aopalliance.sourceforge.net/).
+Licensed under the Public Domain.
+
+This product uses software developed at
+Tanuki Software (http://www.tanukisoftware.com/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+Jasypt (http://jasypt.sourceforge.net/).
+Licensed under the Apache License 2.0.
+
+This product uses software developed at
+JLine (http://jline.sourceforge.net).
+Licensed under the BSD License.
+
+This product uses software developed at
+SLF4J (http://www.slf4j.org/).
+Licensed under the MIT License.
+
+This product uses software developed at
+SpringSource (http://www.springsource.org/).
+Licensed under the Apache License 2.0.
+
+This product includes software from http://www.json.org.
+Copyright (c) 2002 JSON.org
+
+
+III. License Summary
+- Apache License 2.0
+- BSD License
+- EPL License
+- MIT License
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/pom.xml
----------------------------------------------------------------------
diff --git a/shell/command-api/pom.xml b/shell/command-api/pom.xml
new file mode 100644
index 0000000..7e453f8
--- /dev/null
+++ b/shell/command-api/pom.xml
@@ -0,0 +1,131 @@
+<?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.shell</groupId>
+ <artifactId>shell</artifactId>
+ <version>3.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>org.apache.karaf.shell.command.api</artifactId>
+ <packaging>bundle</packaging>
+ <name>Apache Karaf :: Shell :: Command :: API</name>
+ <description>Action and Command API, support classes for implementing commands</description>
+
+ <properties>
+ <appendedResourcesDirectory>${basedir}/../../etc/appended-resources</appendedResourcesDirectory>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.core</artifactId>
+ <scope>provided</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.osgi</groupId>
+ <artifactId>org.osgi.compendium</artifactId>
+ <scope>provided</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.aries.blueprint</groupId>
+ <artifactId>org.apache.aries.blueprint.api</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.aries.blueprint</groupId>
+ <artifactId>org.apache.aries.blueprint.core</artifactId>
+ <scope>provided</scope>
+ <optional>true</optional>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</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>
+ <resource>
+ <directory>${project.basedir}/src/main/filtered-resources</directory>
+ <filtering>true</filtering>
+ <includes>
+ <include>**/*</include>
+ </includes>
+ </resource>
+ </resources>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.felix</groupId>
+ <artifactId>maven-bundle-plugin</artifactId>
+ <configuration>
+ <instructions>
+ <Import-Package>
+ *
+ </Import-Package>
+ <Export-Package>
+ org.apache.karaf.shell.commands;version=${project.version},
+ org.apache.karaf.shell.commands;version=2.3.0,
+ org.apache.karaf.shell.commands.basic;version=${project.version},
+ org.apache.karaf.shell.commands.basic;version=2.3.0,
+ org.apache.karaf.shell.commands.converter;version=${project.version},
+ org.apache.karaf.shell.commands.converter;version=2.3.0,
+ org.apache.karaf.shell.commands.meta;version=${project.version},
+ org.apache.karaf.shell.commands.meta;version=2.3.0,
+ org.apache.karaf.shell.console;version=${project.version},
+ org.apache.karaf.shell.console;version=2.3.0,
+ org.apache.karaf.shell.console.commands;version=${project.version},
+ org.apache.karaf.shell.console.commands;version=2.3.0,
+ org.apache.karaf.shell.console.completer;version=${project.version},
+ org.apache.karaf.shell.console.completer;version=2.3.0,
+ org.apache.karaf.shell.inject;version=${project.version},
+ </Export-Package>
+ </instructions>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/filtered-resources/org/apache/karaf/shell/console/branding-ssh.properties
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/filtered-resources/org/apache/karaf/shell/console/branding-ssh.properties b/shell/command-api/src/main/filtered-resources/org/apache/karaf/shell/console/branding-ssh.properties
new file mode 100644
index 0000000..978484b
--- /dev/null
+++ b/shell/command-api/src/main/filtered-resources/org/apache/karaf/shell/console/branding-ssh.properties
@@ -0,0 +1,34 @@
+##
+## 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.
+##
+
+welcome = \
+\u001B[36m __ __ ____ \u001B[0m\r\n\
+\u001B[36m / //_/____ __________ _/ __/ \u001B[0m\r\n\
+\u001B[36m / ,< / __ `/ ___/ __ `/ /_ \u001B[0m\r\n\
+\u001B[36m / /| |/ /_/ / / / /_/ / __/ \u001B[0m\r\n\
+\u001B[36m /_/ |_|\\__,_/_/ \\__,_/_/ \u001B[0m\r\n\
+\r\n\
+\u001B[1m Apache Karaf\u001B[0m (${project.version})\r\n\
+\r\n\
+Hit '\u001B[1m<tab>\u001B[0m' for a list of available commands\r\n\
+ and '\u001B[1m[cmd] --help\u001B[0m' for help on a specific command.\r\n\
+Hit '\u001B[1msystem:shutdown\u001B[0m' to shutdown Karaf.\r\n\
+Hit '\u001B[1m<ctrl-d>\u001B[0m' or type '\u001B[1mlogout\u001B[0m' to disconnect shell from current session.\r\n
+
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/filtered-resources/org/apache/karaf/shell/console/branding.properties
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/filtered-resources/org/apache/karaf/shell/console/branding.properties b/shell/command-api/src/main/filtered-resources/org/apache/karaf/shell/console/branding.properties
new file mode 100644
index 0000000..3fbcb0a
--- /dev/null
+++ b/shell/command-api/src/main/filtered-resources/org/apache/karaf/shell/console/branding.properties
@@ -0,0 +1,33 @@
+##
+## 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.
+##
+
+welcome = \
+\u001B[36m __ __ ____ \u001B[0m\r\n\
+\u001B[36m / //_/____ __________ _/ __/ \u001B[0m\r\n\
+\u001B[36m / ,< / __ `/ ___/ __ `/ /_ \u001B[0m\r\n\
+\u001B[36m / /| |/ /_/ / / / /_/ / __/ \u001B[0m\r\n\
+\u001B[36m /_/ |_|\\__,_/_/ \\__,_/_/ \u001B[0m\r\n\
+\r\n\
+\u001B[1m Apache Karaf\u001B[0m (${project.version})\r\n\
+\r\n\
+Hit '\u001B[1m<tab>\u001B[0m' for a list of available commands\r\n\
+ and '\u001B[1m[cmd] --help\u001B[0m' for help on a specific command.\r\n\
+Hit '\u001B[1m<ctrl-d>\u001B[0m' or type '\u001B[1msystem:shutdown\u001B[0m' or '\u001B[1mlogout\u001B[0m' to shutdown Karaf.\r\n
+
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Action.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Action.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Action.java
new file mode 100644
index 0000000..0727f24
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Action.java
@@ -0,0 +1,29 @@
+/*
+ * 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.felix.gogo.commands;
+
+import org.apache.felix.service.command.CommandSession;
+
+@Deprecated
+public interface Action {
+
+ Object execute(CommandSession session) throws Exception;
+
+}
+
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Argument.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Argument.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Argument.java
new file mode 100644
index 0000000..33c15bf
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Argument.java
@@ -0,0 +1,49 @@
+/*
+ * 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.felix.gogo.commands;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Represents a positional argument on a command line (as opposed to an optional named {@link Option}
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+@Deprecated
+public @interface Argument {
+
+ public static final String DEFAULT_STRING = "DEFAULT";
+
+ String DEFAULT = "##default";
+
+ String name() default DEFAULT;
+
+ String description() default "";
+
+ boolean required() default false;
+
+ int index() default 0;
+
+ boolean multiValued() default false;
+
+ String valueToShowInHelp() default DEFAULT_STRING;
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Command.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Command.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Command.java
new file mode 100644
index 0000000..10c494a
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Command.java
@@ -0,0 +1,53 @@
+/*
+ * 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.felix.gogo.commands;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Used to denote a class represents a command which is executable within a shell/scope or as a
+ * command line process.
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Deprecated
+public @interface Command {
+ /**
+ * Returns the scope or sub shell of the command
+ */
+ String scope();
+
+ /**
+ * REturns the name of the command if used inside a shell
+ */
+ String name();
+
+ /**
+ * Returns the description of the command which is used to generate command line help
+ */
+ String description() default "";
+
+ /**
+ * Returns a detailed description of the command
+ */
+ String detailedDescription() default "";
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CommandException.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CommandException.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CommandException.java
new file mode 100644
index 0000000..3c02d63
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CommandException.java
@@ -0,0 +1,63 @@
+/*
+ * 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.felix.gogo.commands;
+
+import org.apache.karaf.shell.commands.ansi.SimpleAnsi;
+
+/**
+ * Base class for exceptions thrown when executing commands.
+ */
+@Deprecated
+public class CommandException extends Exception {
+
+ private String help;
+
+ public CommandException() {
+ }
+
+ public CommandException(String message) {
+ super(message);
+ }
+
+ public CommandException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public CommandException(Throwable cause) {
+ super(cause);
+ }
+
+ public CommandException(String help, String message) {
+ super(message);
+ this.help = help;
+ }
+
+ public CommandException(String help, String message, Throwable cause) {
+ super(message, cause);
+ this.help = help;
+ }
+
+ public String getNiceHelp() {
+ return help != null ? help
+ : SimpleAnsi.COLOR_RED + "Error executing command: "
+ + getMessage() != null ? getMessage() : getClass().getName()
+ + SimpleAnsi.COLOR_DEFAULT;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CommandWithAction.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CommandWithAction.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CommandWithAction.java
new file mode 100644
index 0000000..e09cf64
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CommandWithAction.java
@@ -0,0 +1,32 @@
+/*
+ * 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.felix.gogo.commands;
+
+import org.apache.felix.service.command.Function;
+
+@Deprecated
+public interface CommandWithAction extends Function {
+
+ Class<? extends Action> getActionClass();
+
+ Action createNewAction();
+
+ void releaseAction(Action action) throws Exception;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CompleterValues.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CompleterValues.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CompleterValues.java
new file mode 100644
index 0000000..99129e5
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/CompleterValues.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.felix.gogo.commands;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Represents a method which can return a List or Array of values used for a
+ * {@link org.apache.karaf.shell.console.Completer}
+ * which is associated with the index of an
+ * {@link org.apache.karaf.shell.commands.Argument}
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.METHOD, ElementType.FIELD})
+@Deprecated
+public @interface CompleterValues {
+ int index() default 0;
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Option.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Option.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Option.java
new file mode 100644
index 0000000..1ce6f75
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/Option.java
@@ -0,0 +1,48 @@
+/*
+ * 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.felix.gogo.commands;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+/**
+ * Used to mark an optional named command line option who's name typically starts with "--"
+ */
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+@Deprecated
+public @interface Option {
+
+ public static final String DEFAULT_STRING = "DEFAULT";
+
+ String name();
+
+ String[] aliases() default {};
+
+ String description() default "";
+
+ boolean required() default false;
+
+ boolean multiValued() default false;
+
+ String valueToShowInHelp() default DEFAULT_STRING;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/SubShell.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/SubShell.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/SubShell.java
new file mode 100644
index 0000000..0206964
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/SubShell.java
@@ -0,0 +1,46 @@
+/*
+ * 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.felix.gogo.commands;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+@Deprecated
+public @interface SubShell {
+
+ /**
+ * Returns the name of the command if used inside a shell
+ */
+ String name();
+
+ /**
+ * Returns the description of the command which is used to generate command line help
+ */
+ String description() default "";
+
+ /**
+ * Returns a detailed description of the command
+ */
+ String detailedDescription() default "";
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java
new file mode 100644
index 0000000..809ed67
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java
@@ -0,0 +1,64 @@
+/*
+ * 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.felix.gogo.commands.basic;
+
+import java.util.List;
+
+import org.apache.felix.gogo.commands.Action;
+import org.apache.felix.gogo.commands.CommandWithAction;
+import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.Function;
+
+@Deprecated
+public abstract class AbstractCommand implements Function, CommandWithAction {
+
+ public Object execute(CommandSession session, List<Object> arguments) throws Exception {
+ Action action = createNewAction();
+ try {
+ if (getPreparator().prepare(action, session, arguments)) {
+ return action.execute(session);
+ } else {
+ return null;
+ }
+ } finally {
+ releaseAction(action);
+ }
+ }
+
+ public Class<? extends Action> getActionClass() {
+ return createNewAction().getClass();
+ }
+
+ public abstract Action createNewAction();
+
+ /**
+ * Release the used Action.
+ * This method has to be overridden for pool based Actions.
+ * @param action Action that was executed
+ * @throws Exception if something went wrong during the Action release
+ */
+ public void releaseAction(Action action) throws Exception {
+ // Do nothing by default (stateful)
+ }
+
+ protected ActionPreparator getPreparator() throws Exception {
+ return new DefaultActionPreparator();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java
new file mode 100644
index 0000000..65fe24e
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java
@@ -0,0 +1,31 @@
+/*
+ * 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.felix.gogo.commands.basic;
+
+import java.util.List;
+
+import org.apache.felix.gogo.commands.Action;
+import org.apache.felix.service.command.CommandSession;
+
+@Deprecated
+public interface ActionPreparator {
+
+ boolean prepare(Action action, CommandSession session, List<Object> arguments) throws Exception;
+
+}
http://git-wip-us.apache.org/repos/asf/karaf/blob/1ee78df9/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
----------------------------------------------------------------------
diff --git a/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
new file mode 100644
index 0000000..6b7865e
--- /dev/null
+++ b/shell/command-api/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
@@ -0,0 +1,566 @@
+/*
+ * 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.felix.gogo.commands.basic;
+
+import static org.apache.karaf.shell.commands.ansi.SimpleAnsi.COLOR_DEFAULT;
+import static org.apache.karaf.shell.commands.ansi.SimpleAnsi.COLOR_RED;
+import static org.apache.karaf.shell.commands.ansi.SimpleAnsi.INTENSITY_BOLD;
+import static org.apache.karaf.shell.commands.ansi.SimpleAnsi.INTENSITY_NORMAL;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.*;
+import java.io.PrintStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.felix.gogo.commands.CommandException;
+import org.apache.felix.gogo.commands.Option;
+import org.apache.felix.gogo.commands.Action;
+import org.apache.felix.gogo.commands.Argument;
+import org.apache.felix.gogo.commands.Command;
+import org.apache.felix.gogo.commands.converter.DefaultConverter;
+import org.apache.felix.gogo.commands.converter.GenericType;
+import org.apache.felix.service.command.CommandSession;
+import org.apache.karaf.shell.console.NameScoping;
+
+@Deprecated
+public class DefaultActionPreparator implements ActionPreparator {
+
+ public static final Option HELP = new Option() {
+ public String name() {
+ return "--help";
+ }
+
+ public String[] aliases() {
+ return new String[]{};
+ }
+
+ public String description() {
+ return "Display this help message";
+ }
+
+ public boolean required() {
+ return false;
+ }
+
+ public boolean multiValued() {
+ return false;
+ }
+
+ public String valueToShowInHelp() {
+ return Option.DEFAULT_STRING;
+ }
+
+ public Class<? extends Annotation> annotationType() {
+ return Option.class;
+ }
+ };
+
+ public boolean prepare(Action action, CommandSession session, List<Object> params) throws Exception {
+ Map<Option, Field> options = new HashMap<Option, Field>();
+ Map<Argument, Field> arguments = new HashMap<Argument, Field>();
+ List<Argument> orderedArguments = new ArrayList<Argument>();
+ // Introspect
+ for (Class type = action.getClass(); type != null; type = type.getSuperclass()) {
+ for (Field field : type.getDeclaredFields()) {
+ Option option = field.getAnnotation(Option.class);
+ if (option != null) {
+ options.put(option, field);
+ }
+ Argument argument = field.getAnnotation(Argument.class);
+ if (argument != null) {
+ if (Argument.DEFAULT.equals(argument.name())) {
+ final Argument delegate = argument;
+ final String name = field.getName();
+ argument = new Argument() {
+ public String name() {
+ return name;
+ }
+
+ public String description() {
+ return delegate.description();
+ }
+
+ public boolean required() {
+ return delegate.required();
+ }
+
+ public int index() {
+ return delegate.index();
+ }
+
+ public boolean multiValued() {
+ return delegate.multiValued();
+ }
+
+ public String valueToShowInHelp() {
+ return delegate.valueToShowInHelp();
+ }
+
+ public Class<? extends Annotation> annotationType() {
+ return delegate.annotationType();
+ }
+ };
+ }
+ arguments.put(argument, field);
+ int index = argument.index();
+ while (orderedArguments.size() <= index) {
+ orderedArguments.add(null);
+ }
+ if (orderedArguments.get(index) != null) {
+ throw new IllegalArgumentException("Duplicate argument index: " + index);
+ }
+ orderedArguments.set(index, argument);
+ }
+ }
+ }
+ // Check indexes are correct
+ for (int i = 0; i < orderedArguments.size(); i++) {
+ if (orderedArguments.get(i) == null) {
+ throw new IllegalArgumentException("Missing argument for index: " + i);
+ }
+ }
+ // Populate
+ Map<Option, Object> optionValues = new HashMap<Option, Object>();
+ Map<Argument, Object> argumentValues = new HashMap<Argument, Object>();
+ boolean processOptions = true;
+ int argIndex = 0;
+ for (Iterator<Object> it = params.iterator(); it.hasNext(); ) {
+ Object param = it.next();
+ // Check for help
+ if (HELP.name().equals(param) || Arrays.asList(HELP.aliases()).contains(param)) {
+ printUsage(session, action, options, arguments, System.out);
+ return false;
+ }
+ if (processOptions && param instanceof String && ((String) param).startsWith("-")) {
+ boolean isKeyValuePair = ((String) param).indexOf('=') != -1;
+ String name;
+ Object value = null;
+ if (isKeyValuePair) {
+ name = ((String) param).substring(0, ((String) param).indexOf('='));
+ value = ((String) param).substring(((String) param).indexOf('=') + 1);
+ } else {
+ name = (String) param;
+ }
+ Option option = null;
+ for (Option opt : options.keySet()) {
+ if (name.equals(opt.name()) || Arrays.asList(opt.aliases()).contains(name)) {
+ option = opt;
+ break;
+ }
+ }
+ if (option == null) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ if (command != null) {
+ throw new CommandException(COLOR_RED
+ + "Error executing command "
+ + command.scope() + ":"
+ + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL
+ + " undefined option "
+ + INTENSITY_BOLD + param + INTENSITY_NORMAL
+ + COLOR_DEFAULT,
+ "Undefined option: " + param
+ );
+ } else {
+ throw new CommandException("Undefined option: " + param);
+ }
+ }
+ Field field = options.get(option);
+ if (value == null && (field.getType() == boolean.class || field.getType() == Boolean.class)) {
+ value = Boolean.TRUE;
+ }
+ if (value == null && it.hasNext()) {
+ value = it.next();
+ }
+ if (value == null) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ if (command != null) {
+ throw new CommandException(COLOR_RED
+ + "Error executing command "
+ + command.scope() + ":"
+ + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL
+ + " missing value for option "
+ + INTENSITY_BOLD + param + INTENSITY_NORMAL
+ + COLOR_DEFAULT,
+ "Missing value for option: " + param
+ );
+ } else {
+ throw new CommandException("Missing value for option: " + param);
+ }
+ }
+ if (option.multiValued()) {
+ List<Object> l = (List<Object>) optionValues.get(option);
+ if (l == null) {
+ l = new ArrayList<Object>();
+ optionValues.put(option, l);
+ }
+ l.add(value);
+ } else {
+ optionValues.put(option, value);
+ }
+ } else {
+ processOptions = false;
+ if (argIndex >= orderedArguments.size()) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ if (command != null) {
+ throw new CommandException(COLOR_RED
+ + "Error executing command "
+ + command.scope() + ":"
+ + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL
+ + ": too many arguments specified"
+ + INTENSITY_BOLD + param + INTENSITY_NORMAL
+ + COLOR_DEFAULT,
+ "Too many arguments specified"
+ );
+ } else {
+ throw new CommandException("Too many arguments specified");
+ }
+ }
+ Argument argument = orderedArguments.get(argIndex);
+ if (!argument.multiValued()) {
+ argIndex++;
+ }
+ if (argument.multiValued()) {
+ List<Object> l = (List<Object>) argumentValues.get(argument);
+ if (l == null) {
+ l = new ArrayList<Object>();
+ argumentValues.put(argument, l);
+ }
+ l.add(param);
+ } else {
+ argumentValues.put(argument, param);
+ }
+ }
+ }
+ // Check required arguments / options
+ for (Option option : options.keySet()) {
+ if (option.required() && optionValues.get(option) == null) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ if (command != null) {
+ throw new CommandException(COLOR_RED
+ + "Error executing command "
+ + command.scope() + ":"
+ + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL
+ + ": option "
+ + INTENSITY_BOLD + option.name() + INTENSITY_NORMAL
+ + " is required"
+ + COLOR_DEFAULT,
+ "Option " + option.name() + " is required"
+ );
+ } else {
+ throw new CommandException("Option " + option.name() + " is required");
+ }
+ }
+ }
+ for (Argument argument : orderedArguments) {
+ if (argument.required() && argumentValues.get(argument) == null) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ if (command != null) {
+ throw new CommandException(COLOR_RED
+ + "Error executing command "
+ + command.scope() + ":"
+ + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL
+ + ": argument "
+ + INTENSITY_BOLD + argument.name() + INTENSITY_NORMAL
+ + " is required"
+ + COLOR_DEFAULT,
+ "Argument " + argument.name() + " is required"
+ );
+ } else {
+ throw new CommandException("Argument " + argument.name() + " is required");
+ }
+ }
+ }
+ // Convert and inject values
+ for (Map.Entry<Option, Object> entry : optionValues.entrySet()) {
+ Field field = options.get(entry.getKey());
+ Object value;
+ try {
+ value = convert(action, session, entry.getValue(), field.getGenericType());
+ } catch (Exception e) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ if (command != null) {
+ throw new CommandException(COLOR_RED
+ + "Error executing command "
+ + command.scope() + ":"
+ + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL
+ + ": unable to convert option "
+ + INTENSITY_BOLD + entry.getKey().name() + INTENSITY_NORMAL
+ + " with value '" + entry.getValue() + "' to type "
+ + new GenericType(field.getGenericType()).toString()
+ + COLOR_DEFAULT,
+ "Unable to convert option " + entry.getKey().name() + " with value '"
+ + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(),
+ e
+ );
+ } else {
+ throw new CommandException("Unable to convert option " + entry.getKey().name() + " with value '"
+ + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(),
+ e);
+ }
+ }
+ field.setAccessible(true);
+ field.set(action, value);
+ }
+ for (Map.Entry<Argument, Object> entry : argumentValues.entrySet()) {
+ Field field = arguments.get(entry.getKey());
+ Object value;
+ try {
+ value = convert(action, session, entry.getValue(), field.getGenericType());
+ } catch (Exception e) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ if (command != null) {
+ throw new CommandException(COLOR_RED
+ + "Error executing command "
+ + command.scope() + ":"
+ + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL
+ + ": unable to convert argument "
+ + INTENSITY_BOLD + entry.getKey().name() + INTENSITY_NORMAL
+ + " with value '" + entry.getValue() + "' to type "
+ + new GenericType(field.getGenericType()).toString()
+ + COLOR_DEFAULT,
+ "Unable to convert argument " + entry.getKey().name() + " with value '"
+ + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(),
+ e
+ );
+ } else {
+ throw new CommandException("Unable to convert argument " + entry.getKey().name() + " with value '"
+ + entry.getValue() + "' to type " + new GenericType(field.getGenericType()).toString(),
+ e);
+ }
+ }
+ field.setAccessible(true);
+ field.set(action, value);
+ }
+ return true;
+ }
+
+ protected void printUsage(CommandSession session, Action action, Map<Option, Field> optionsMap, Map<Argument, Field> argsMap, PrintStream out) {
+ Command command = action.getClass().getAnnotation(Command.class);
+ if (command != null) {
+
+ List<Argument> arguments = new ArrayList<Argument>(argsMap.keySet());
+ Collections.sort(arguments, new Comparator<Argument>() {
+ public int compare(Argument o1, Argument o2) {
+ return Integer.valueOf(o1.index()).compareTo(Integer.valueOf(o2.index()));
+ }
+ });
+ Set<Option> options = new HashSet<Option>(optionsMap.keySet());
+ options.add(HELP);
+ boolean globalScope = NameScoping.isGlobalScope(session, command.scope());
+ if (command != null && (command.description() != null || command.name() != null)) {
+ out.println(INTENSITY_BOLD + "DESCRIPTION" + INTENSITY_NORMAL);
+ out.print(" ");
+ if (command.name() != null) {
+ if (globalScope) {
+ out.println(INTENSITY_BOLD + command.name() + INTENSITY_NORMAL);
+ } else {
+ out.println(command.scope() + ":" + INTENSITY_BOLD + command.name() + INTENSITY_NORMAL);
+ }
+ out.println();
+ }
+ out.print("\t");
+ out.println(command.description());
+ out.println();
+ }
+ StringBuffer syntax = new StringBuffer();
+ if (command != null) {
+ if (globalScope) {
+ syntax.append(command.name());
+ } else {
+ syntax.append(String.format("%s:%s", command.scope(), command.name()));
+ }
+ }
+ if (options.size() > 0) {
+ syntax.append(" [options]");
+ }
+ if (arguments.size() > 0) {
+ syntax.append(' ');
+ for (Argument argument : arguments) {
+ if (!argument.required()) {
+ syntax.append(String.format("[%s] ", argument.name()));
+ } else {
+ syntax.append(String.format("%s ", argument.name()));
+ }
+ }
+ }
+ int width = getWidth(session);
+ out.println(INTENSITY_BOLD + "SYNTAX" + INTENSITY_NORMAL);
+ out.print(" ");
+ out.println(syntax.toString());
+ out.println();
+ if (arguments.size() > 0) {
+ out.println(INTENSITY_BOLD + "ARGUMENTS" + INTENSITY_NORMAL);
+ for (Argument argument : arguments) {
+ out.print(" ");
+ out.println(INTENSITY_BOLD + argument.name() + INTENSITY_NORMAL);
+
+ printFormatted(" ", argument.description(), width, out);
+ if (!argument.required()) {
+ if (argument.valueToShowInHelp() != null && argument.valueToShowInHelp().length() != 0) {
+ try {
+ if (Argument.DEFAULT_STRING.equals(argument.valueToShowInHelp())) {
+ argsMap.get(argument).setAccessible(true);
+ Object o = argsMap.get(argument).get(action);
+ printObjectDefaultsTo(out, o);
+ } else {
+ printDefaultsTo(out, argument.valueToShowInHelp());
+ }
+ } catch (Throwable t) {
+ // Ignore
+ }
+ }
+ }
+ }
+ out.println();
+ }
+ if (options.size() > 0) {
+ out.println(INTENSITY_BOLD + "OPTIONS" + INTENSITY_NORMAL);
+ for (Option option : options) {
+ String opt = option.name();
+ for (String alias : option.aliases()) {
+ opt += ", " + alias;
+ }
+ out.print(" ");
+ out.println(INTENSITY_BOLD + opt + INTENSITY_NORMAL);
+ printFormatted(" ", option.description(), width, out);
+ if (option.valueToShowInHelp() != null && option.valueToShowInHelp().length() != 0) {
+ try {
+ if (Option.DEFAULT_STRING.equals(option.valueToShowInHelp())) {
+ optionsMap.get(option).setAccessible(true);
+ Object o = optionsMap.get(option).get(action);
+ printObjectDefaultsTo(out, o);
+ } else {
+ printDefaultsTo(out, option.valueToShowInHelp());
+ }
+ } catch (Throwable t) {
+ // Ignore
+ }
+ }
+ }
+ out.println();
+ }
+ if (command.detailedDescription().length() > 0) {
+ out.println(INTENSITY_BOLD + "DETAILS" + INTENSITY_NORMAL);
+ String desc = loadDescription(action.getClass(), command.detailedDescription());
+ printFormatted(" ", desc, width, out);
+ }
+ }
+ }
+
+ private void printObjectDefaultsTo(PrintStream out, Object o) {
+ if (o != null
+ && (!(o instanceof Boolean) || ((Boolean) o))
+ && (!(o instanceof Number) || ((Number) o).doubleValue() != 0.0)) {
+ printDefaultsTo(out, o.toString());
+ }
+ }
+
+ private void printDefaultsTo(PrintStream out, String value) {
+ out.print(" (defaults to ");
+ out.print(value);
+ out.println(")");
+ }
+
+ protected String loadDescription(Class clazz, String desc) {
+ if (desc.startsWith("classpath:")) {
+ InputStream is = clazz.getResourceAsStream(desc.substring("classpath:".length()));
+ if (is == null) {
+ is = clazz.getClassLoader().getResourceAsStream(desc.substring("classpath:".length()));
+ }
+ if (is == null) {
+ desc = "Unable to load description from " + desc;
+ } else {
+ try {
+ Reader r = new InputStreamReader(is);
+ StringWriter sw = new StringWriter();
+ int c;
+ while ((c = r.read()) != -1) {
+ sw.append((char) c);
+ }
+ desc = sw.toString();
+ } catch (IOException e) {
+ desc = "Unable to load description from " + desc;
+ } finally {
+ try {
+ is.close();
+ } catch (IOException e) {
+ // Ignore
+ }
+ }
+ }
+ }
+ return desc;
+ }
+
+ // TODO move this to a helper class?
+ public static void printFormatted(String prefix, String str, int termWidth, PrintStream out) {
+ printFormatted(prefix, str, termWidth, out, true);
+ }
+
+ public static void printFormatted(String prefix, String str, int termWidth, PrintStream out, boolean prefixFirstLine) {
+ int pfxLen = length(prefix);
+ int maxwidth = termWidth - pfxLen;
+ Pattern wrap = Pattern.compile("(\\S\\S{" + maxwidth + ",}|.{1," + maxwidth + "})(\\s+|$)");
+ int cur = 0;
+ while (cur >= 0) {
+ int lst = str.indexOf('\n', cur);
+ String s = (lst >= 0) ? str.substring(cur, lst) : str.substring(cur);
+ if (s.length() == 0) {
+ out.println();
+ } else {
+ Matcher m = wrap.matcher(s);
+ while (m.find()) {
+ if (cur > 0 || prefixFirstLine) {
+ out.print(prefix);
+ }
+ out.println(m.group());
+ }
+ }
+ if (lst >= 0) {
+ cur = lst + 1;
+ } else {
+ break;
+ }
+ }
+ }
+
+ public static int length(String str) {
+ return str.length();
+ }
+
+ protected Object convert(Action action, CommandSession session, Object value, Type toType) throws Exception {
+ if (toType == String.class) {
+ return value != null ? value.toString() : null;
+ }
+ return new DefaultConverter(action.getClass().getClassLoader()).convert(value, toType);
+ }
+
+ private int getWidth(CommandSession session) {
+ Object cols = session.get("COLUMNS");
+ return (cols != null && cols instanceof Integer) ? (Integer)cols : 80;
+ }
+}