You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@felix.apache.org by gn...@apache.org on 2009/07/03 18:07:12 UTC
svn commit: r790958 - in /felix/trunk/gogo: ./ gogo.commands/
gogo.commands/src/ gogo.commands/src/main/ gogo.commands/src/main/java/
gogo.commands/src/main/java/org/ gogo.commands/src/main/java/org/apache/
gogo.commands/src/main/java/org/apache/felix/...
Author: gnodet
Date: Fri Jul 3 16:07:10 2009
New Revision: 790958
URL: http://svn.apache.org/viewvc?rev=790958&view=rev
Log:
Add commands, fix parser, remove DS dependency, remove equinox support
Added:
felix/trunk/gogo/gogo.commands/
felix/trunk/gogo/gogo.commands/pom.xml
- copied, changed from r790473, felix/trunk/gogo/gogo.runtime/pom.xml
felix/trunk/gogo/gogo.commands/src/
felix/trunk/gogo/gogo.commands/src/main/
felix/trunk/gogo/gogo.commands/src/main/java/
felix/trunk/gogo/gogo.commands/src/main/java/org/
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Action.java
- copied, changed from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Argument.java
- copied, changed from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Command.java
- copied, changed from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Option.java
- copied, changed from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java
- copied, changed from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/SimpleCommand.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/DefaultConverter.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/GenericType.java
felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/ReifiedType.java
felix/trunk/gogo/gogo.commands/src/test/
felix/trunk/gogo/gogo.commands/src/test/java/
felix/trunk/gogo/gogo.commands/src/test/java/org/
felix/trunk/gogo/gogo.commands/src/test/java/org/apache/
felix/trunk/gogo/gogo.commands/src/test/java/org/apache/felix/
felix/trunk/gogo/gogo.commands/src/test/java/org/apache/felix/gogo/
felix/trunk/gogo/gogo.commands/src/test/java/org/apache/felix/gogo/commands/
felix/trunk/gogo/gogo.commands/src/test/java/org/apache/felix/gogo/commands/TestCommands.java
Removed:
felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/equinox/Equinox.java
felix/trunk/gogo/src/main/java/org/osgi/framework/boot/SystemBundle.java
Modified:
felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java
felix/trunk/gogo/gogo.runtime/pom.xml
felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/osgi/OSGiShell.java
felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java
felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java
felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java
felix/trunk/gogo/gogo.runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java
felix/trunk/gogo/pom.xml
Copied: felix/trunk/gogo/gogo.commands/pom.xml (from r790473, felix/trunk/gogo/gogo.runtime/pom.xml)
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/pom.xml?p2=felix/trunk/gogo/gogo.commands/pom.xml&p1=felix/trunk/gogo/gogo.runtime/pom.xml&r1=790473&r2=790958&rev=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.runtime/pom.xml (original)
+++ felix/trunk/gogo/gogo.commands/pom.xml Fri Jul 3 16:07:10 2009
@@ -25,8 +25,8 @@
</parent>
<modelVersion>4.0.0</modelVersion>
<packaging>bundle</packaging>
- <name>Apache Felix Gogo Shell Runtime</name>
- <artifactId>org.apache.felix.gogo.runtime</artifactId>
+ <name>Apache Felix Gogo Shell Commands</name>
+ <artifactId>org.apache.felix.gogo.commands</artifactId>
<version>1.0.0-SNAPSHOT</version>
<dependencies>
<dependency>
@@ -40,9 +40,8 @@
<scope>provided</scope>
</dependency>
<dependency>
- <groupId>junit</groupId>
- <artifactId>junit</artifactId>
- <scope>test</scope>
+ <groupId>org.apache.felix.gogo</groupId>
+ <artifactId>org.apache.felix.gogo.runtime</artifactId>
</dependency>
</dependencies>
<build>
@@ -55,20 +54,17 @@
<configuration>
<instructions>
<Export-Package>
- org.osgi.service.command; version=1.0.0,
- org.osgi.service.threadio; version=1.0.0
+ org.apache.felix.gogo.commands*;version=${pom.version},
</Export-Package>
<Import-Package>
- org.osgi.service.component*; resolution:=optional,
- org.osgi.service.log*; resolution:=optional,
- org.osgi.service.packageadmin*; resolution:=optional,
- org.osgi.service.startlevel*; resolution:=optional,
+ !org.apache.felix.gogo.commands.basic,
+ !org.apache.felix.gogo.commands.converter,
*
</Import-Package>
- <Private-Package>org.apache.felix.gogo.*</Private-Package>
<Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
<Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
- <Bundle-Activator>org.apache.felix.gogo.runtime.Activator</Bundle-Activator>
+ <_versionpolicy>[$(version;==;$(@)),$(version;+;$(@)))</_versionpolicy>
+ <_removeheaders>Private-Package,Ignore-Package</_removeheaders>
</instructions>
</configuration>
</plugin>
Copied: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Action.java (from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java)
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Action.java?p2=felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Action.java&p1=felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java&r1=790473&r2=790958&rev=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java (original)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Action.java Fri Jul 3 16:07:10 2009
@@ -16,33 +16,13 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.gogo.console.stdio;
+package org.apache.felix.gogo.commands;
-import org.osgi.service.command.CommandProcessor;
-import org.osgi.service.component.ComponentContext;
+import org.osgi.service.command.CommandSession;
-public class StdioConsole extends Thread
+public interface Action
{
- final Console console = new Console();
- public StdioConsole()
- {
- super("StdioConsole");
- }
+ Object execute(CommandSession session) throws Exception;
- public void close()
- {
- console.close();
- interrupt();
- }
-
- public void setProcessor(CommandProcessor processor)
- {
- console.setSession(processor.createSession(System.in, System.out, System.err));
- }
-
- public void run()
- {
- console.run();
- }
-}
\ No newline at end of file
+}
Copied: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Argument.java (from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java)
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Argument.java?p2=felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Argument.java&p1=felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java&r1=790473&r2=790958&rev=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java (original)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Argument.java Fri Jul 3 16:07:10 2009
@@ -16,33 +16,24 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.gogo.console.stdio;
+package org.apache.felix.gogo.commands;
-import org.osgi.service.command.CommandProcessor;
-import org.osgi.service.component.ComponentContext;
-
-public class StdioConsole extends Thread
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface Argument
{
- final Console console = new Console();
+ String name() default "VAL";
+
+ String description() default "";
+
+ boolean required() default false;
+
+ int index() default 0;
- public StdioConsole()
- {
- super("StdioConsole");
- }
-
- public void close()
- {
- console.close();
- interrupt();
- }
-
- public void setProcessor(CommandProcessor processor)
- {
- console.setSession(processor.createSession(System.in, System.out, System.err));
- }
-
- public void run()
- {
- console.run();
- }
-}
\ No newline at end of file
+ boolean multiValued() default false;
+}
Copied: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Command.java (from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java)
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Command.java?p2=felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Command.java&p1=felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java&r1=790473&r2=790958&rev=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java (original)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Command.java Fri Jul 3 16:07:10 2009
@@ -16,33 +16,20 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.gogo.console.stdio;
+package org.apache.felix.gogo.commands;
-import org.osgi.service.command.CommandProcessor;
-import org.osgi.service.component.ComponentContext;
-
-public class StdioConsole extends Thread
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.TYPE})
+public @interface Command
{
- final Console console = new Console();
-
- public StdioConsole()
- {
- super("StdioConsole");
- }
-
- public void close()
- {
- console.close();
- interrupt();
- }
+ String scope();
- public void setProcessor(CommandProcessor processor)
- {
- console.setSession(processor.createSession(System.in, System.out, System.err));
- }
+ String name();
- public void run()
- {
- console.run();
- }
-}
\ No newline at end of file
+ String description() default "";
+}
Copied: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Option.java (from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java)
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Option.java?p2=felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Option.java&p1=felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java&r1=790473&r2=790958&rev=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java (original)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/Option.java Fri Jul 3 16:07:10 2009
@@ -16,33 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.gogo.console.stdio;
+package org.apache.felix.gogo.commands;
-import org.osgi.service.command.CommandProcessor;
-import org.osgi.service.component.ComponentContext;
-
-public class StdioConsole extends Thread
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+import java.lang.annotation.ElementType;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target({ElementType.FIELD})
+public @interface Option
{
- final Console console = new Console();
+ String name();
+
+ String[] aliases() default {};
+
+ String description() default "";
+
+ boolean required() default false;
+
+ boolean multiValued() default false;
- public StdioConsole()
- {
- super("StdioConsole");
- }
-
- public void close()
- {
- console.close();
- interrupt();
- }
-
- public void setProcessor(CommandProcessor processor)
- {
- console.setSession(processor.createSession(System.in, System.out, System.err));
- }
-
- public void run()
- {
- console.run();
- }
-}
\ No newline at end of file
+}
Copied: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java (from r790473, felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java)
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java?p2=felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java&p1=felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java&r1=790473&r2=790958&rev=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java (original)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/AbstractCommand.java Fri Jul 3 16:07:10 2009
@@ -16,33 +16,28 @@
* specific language governing permissions and limitations
* under the License.
*/
-package org.apache.felix.gogo.console.stdio;
+package org.apache.felix.gogo.commands.basic;
-import org.osgi.service.command.CommandProcessor;
-import org.osgi.service.component.ComponentContext;
+import java.util.List;
-public class StdioConsole extends Thread
-{
- final Console console = new Console();
-
- public StdioConsole()
- {
- super("StdioConsole");
+import org.apache.felix.gogo.commands.basic.DefaultActionPreparator;
+import org.apache.felix.gogo.commands.basic.ActionPreparator;
+import org.apache.felix.gogo.commands.Action;
+import org.osgi.service.command.CommandSession;
+import org.osgi.service.command.Function;
+
+public abstract class AbstractCommand implements Function {
+
+ public Object execute(CommandSession session, List<Object> arguments) throws Exception {
+ Action action = createNewAction();
+ getPreparator().prepare(action, session, arguments);
+ return action.execute(session);
}
- public void close()
- {
- console.close();
- interrupt();
- }
+ protected abstract Action createNewAction() throws Exception;
- public void setProcessor(CommandProcessor processor)
- {
- console.setSession(processor.createSession(System.in, System.out, System.err));
+ protected ActionPreparator getPreparator() throws Exception {
+ return new DefaultActionPreparator();
}
- public void run()
- {
- console.run();
- }
-}
\ No newline at end of file
+}
Added: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java?rev=790958&view=auto
==============================================================================
--- felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java (added)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/ActionPreparator.java Fri Jul 3 16:07:10 2009
@@ -0,0 +1,12 @@
+package org.apache.felix.gogo.commands.basic;
+
+import java.util.List;
+
+import org.osgi.service.command.CommandSession;
+import org.apache.felix.gogo.commands.Action;
+
+public interface ActionPreparator {
+
+ void prepare(Action action, CommandSession session, List<Object> arguments) throws Exception;
+
+}
Added: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java?rev=790958&view=auto
==============================================================================
--- felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java (added)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/DefaultActionPreparator.java Fri Jul 3 16:07:10 2009
@@ -0,0 +1,269 @@
+/**
+ *
+ * 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.lang.annotation.Annotation;
+import java.lang.reflect.Field;
+import java.lang.reflect.Type;
+import java.util.List;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.Arrays;
+import java.util.Set;
+import java.util.HashSet;
+import java.io.PrintStream;
+
+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.basic.ActionPreparator;
+import org.apache.felix.gogo.commands.converter.DefaultConverter;
+import org.osgi.service.command.CommandSession;
+
+public class DefaultActionPreparator implements ActionPreparator {
+
+ protected 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 Class<? extends Annotation> annotationType()
+ {
+ return Option.class;
+ }
+ };
+
+ public void 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) {
+ 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(action.getClass().getAnnotation(Command.class), options.keySet(), arguments.keySet(), System.out);
+ return;
+ }
+ 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.binarySearch(opt.aliases(), name) >= 0) {
+ option = opt;
+ break;
+ }
+ }
+ if (option == null) {
+ throw new IllegalArgumentException("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) {
+ throw new IllegalArgumentException("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()) {
+ throw new IllegalArgumentException("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) {
+ throw new IllegalArgumentException("Option " + option.name() + " is required");
+ }
+ }
+ for (Argument argument : arguments.keySet()) {
+ if (argument.required() && argumentValues.get(argument) == null) {
+ throw new IllegalArgumentException("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 = convert(action, session, entry.getValue(), field.getGenericType());
+ field.setAccessible(true);
+ field.set(action, value);
+ }
+ for (Map.Entry<Argument, Object> entry : argumentValues.entrySet()) {
+ Field field = arguments.get(entry.getKey());
+ Object value = convert(action, session, entry.getValue(), field.getGenericType());
+ field.setAccessible(true);
+ field.set(action, value);
+ }
+ }
+
+ protected void printUsage(Command command, Set<Option> options, Set<Argument> arguments, PrintStream out)
+ {
+ options = new HashSet<Option>(options);
+ options.add(HELP);
+ if (command != null && command.description() != null && command.description().length() > 0)
+ {
+ out.println(command.description());
+ out.println();
+ }
+ String syntax = "syntax: ";
+ if (command != null)
+ {
+ syntax += command.scope() + ":" + command.name();
+ }
+ if (options.size() > 0)
+ {
+ syntax += " [options]";
+ }
+ if (arguments.size() > 0)
+ {
+ syntax += " [arguments]";
+ }
+ out.println(syntax);
+ out.println();
+ if (arguments.size() > 0)
+ {
+ out.println("arguments:");
+ for (Argument argument : arguments)
+ {
+ out.print(" ");
+ out.print(argument.name());
+ out.print(" ");
+ out.print(argument.description());
+ out.println();
+ }
+ out.println();
+ }
+ if (options.size() > 0)
+ {
+ out.println("options:");
+ for (Option option : options)
+ {
+ out.print(" ");
+ out.print(option.name());
+ out.print(" ");
+ if (option.aliases().length > 0)
+ {
+ out.print("(");
+ out.print(Arrays.toString(option.aliases()));
+ out.print(") ");
+ }
+ out.print(option.description());
+ out.println();
+ }
+ out.println();
+ }
+ }
+
+ protected Object convert(Action action, CommandSession session, Object value, Type toType) throws Exception
+ {
+ return new DefaultConverter(action.getClass().getClassLoader()).convert(value, toType);
+ }
+
+}
Added: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/SimpleCommand.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/SimpleCommand.java?rev=790958&view=auto
==============================================================================
--- felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/SimpleCommand.java (added)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/basic/SimpleCommand.java Fri Jul 3 16:07:10 2009
@@ -0,0 +1,71 @@
+/**
+ *
+ * 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.Hashtable;
+
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.BundleContext;
+import org.osgi.service.command.Function;
+import org.apache.felix.gogo.commands.basic.AbstractCommand;
+import org.apache.felix.gogo.commands.Action;
+import org.apache.felix.gogo.commands.Command;
+
+public class SimpleCommand extends AbstractCommand {
+
+ private Class<? extends Action> actionClass;
+
+ public SimpleCommand()
+ {
+ }
+
+ public SimpleCommand(Class<? extends Action> actionClass)
+ {
+ this.actionClass = actionClass;
+ }
+
+ public Class<? extends Action> getActionClass()
+ {
+ return actionClass;
+ }
+
+ public void setActionClass(Class<? extends Action> actionClass)
+ {
+ this.actionClass = actionClass;
+ }
+
+ protected Action createNewAction() throws Exception {
+ return actionClass.newInstance();
+ }
+
+
+ public static ServiceRegistration export(BundleContext context, Class<? extends Action> actionClass)
+ {
+ Command cmd = actionClass.getAnnotation(Command.class);
+ if (cmd == null)
+ {
+ throw new IllegalArgumentException("Action class is not annotated with @Command");
+ }
+ Hashtable props = new Hashtable();
+ props.put("osgi.command.scope", cmd.scope());
+ props.put("osgi.command.function", cmd.name());
+ SimpleCommand command = new SimpleCommand(actionClass);
+ return context.registerService(Function.class.getName(), command, props);
+ }
+
+}
Added: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/DefaultConverter.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/DefaultConverter.java?rev=790958&view=auto
==============================================================================
--- felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/DefaultConverter.java (added)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/DefaultConverter.java Fri Jul 3 16:07:10 2009
@@ -0,0 +1,402 @@
+/**
+ *
+ * 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.converter;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Dictionary;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.Hashtable;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.LinkedHashMap;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.Set;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Queue;
+import java.util.LinkedList;
+import java.util.regex.Pattern;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentHashMap;
+import java.math.BigInteger;
+import java.math.BigDecimal;
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Modifier;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Array;
+import java.lang.reflect.Type;
+import java.lang.reflect.InvocationTargetException;
+
+import org.apache.felix.gogo.commands.converter.ReifiedType;
+
+public class DefaultConverter
+{
+
+ private Object loader;
+
+ public DefaultConverter(Object loader) {
+ this.loader = loader;
+ }
+
+ public Object convert(Object source, Type target) throws Exception {
+ return convert( source, new GenericType(target));
+ }
+
+ public Object convert(Object fromValue, ReifiedType type) throws Exception {
+ // Discard null values
+ if (fromValue == null) {
+ return null;
+ }
+ // If the object is an instance of the type, just return it
+ if (isAssignable(fromValue, type)) {
+ return fromValue;
+ }
+ Object value = convertWithConverters(fromValue, type);
+ if (value == null) {
+ if (fromValue instanceof Number && Number.class.isAssignableFrom(unwrap(toClass(type)))) {
+ return convertToNumber((Number) fromValue, toClass(type));
+ } else if (fromValue instanceof String) {
+ return convertFromString((String) fromValue, toClass(type), loader);
+ } else if (toClass(type).isArray() && (fromValue instanceof Collection || fromValue.getClass().isArray())) {
+ return convertToArray(fromValue, type);
+ } else if (Map.class.isAssignableFrom(toClass(type)) && (fromValue instanceof Map || fromValue instanceof Dictionary)) {
+ return convertToMap(fromValue, type);
+ } else if (Dictionary.class.isAssignableFrom(toClass(type)) && (fromValue instanceof Map || fromValue instanceof Dictionary)) {
+ return convertToDictionary(fromValue, type);
+ } else if (Collection.class.isAssignableFrom(toClass(type)) && (fromValue instanceof Collection || fromValue.getClass().isArray())) {
+ return convertToCollection(fromValue, type);
+ } else {
+ throw new Exception("Unable to convert value " + fromValue + " to type " + type);
+ }
+ }
+ return value;
+ }
+
+ private Object convertWithConverters(Object source, ReifiedType type) throws Exception {
+ Object value = null;
+// for (Converter converter : converters) {
+// if (converter.canConvert(source, type)) {
+// value = converter.convert(source, type);
+// if (value != null) {
+// return value;
+// }
+// }
+// }
+ return value;
+ }
+
+ public Object convertToNumber(Number value, Class toType) throws Exception {
+ toType = unwrap(toType);
+ if (AtomicInteger.class == toType) {
+ return new AtomicInteger((Integer) convertToNumber(value, Integer.class));
+ } else if (AtomicLong.class == toType) {
+ return new AtomicLong((Long) convertToNumber(value, Long.class));
+ } else if (Integer.class == toType) {
+ return value.intValue();
+ } else if (Short.class == toType) {
+ return value.shortValue();
+ } else if (Long.class == toType) {
+ return value.longValue();
+ } else if (Float.class == toType) {
+ return value.floatValue();
+ } else if (Double.class == toType) {
+ return value.doubleValue();
+ } else if (Byte.class == toType) {
+ return value.byteValue();
+ } else if (BigInteger.class == toType) {
+ return new BigInteger(value.toString());
+ } else if (BigDecimal.class == toType) {
+ return new BigDecimal(value.toString());
+ } else {
+ throw new Exception("Unable to convert number " + value + " to " + toType);
+ }
+ }
+
+ public Object convertFromString(String value, Class toType, Object loader) throws Exception {
+ toType = unwrap(toType);
+ if (ReifiedType.class == toType) {
+ try {
+ return GenericType.parse(value, loader);
+ } catch (ClassNotFoundException e) {
+ throw new Exception("Unable to convert", e);
+ }
+ } else if (Class.class == toType) {
+ try {
+ return GenericType.parse(value, loader).getRawClass();
+ } catch (ClassNotFoundException e) {
+ throw new Exception("Unable to convert", e);
+ }
+ } else if (Locale.class == toType) {
+ String[] tokens = value.split("_");
+ if (tokens.length == 1) {
+ return new Locale(tokens[0]);
+ } else if (tokens.length == 2) {
+ return new Locale(tokens[0], tokens[1]);
+ } else if (tokens.length == 3) {
+ return new Locale(tokens[0], tokens[1], tokens[2]);
+ } else {
+ throw new Exception("Invalid locale string:" + value);
+ }
+ } else if (Pattern.class == toType) {
+ return Pattern.compile(value);
+ } else if (Properties.class == toType) {
+ Properties props = new Properties();
+ ByteArrayInputStream in = new ByteArrayInputStream(value.getBytes("UTF8"));
+ props.load(in);
+ return props;
+ } else if (Boolean.class == toType) {
+ if ("yes".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "on".equalsIgnoreCase(value)) {
+ return Boolean.TRUE;
+ } else if ("no".equalsIgnoreCase(value) || "false".equalsIgnoreCase(value) || "off".equalsIgnoreCase(value)) {
+ return Boolean.FALSE;
+ } else {
+ throw new RuntimeException("Invalid boolean value: " + value);
+ }
+ } else if (Integer.class == toType) {
+ return Integer.valueOf(value);
+ } else if (Short.class == toType) {
+ return Short.valueOf(value);
+ } else if (Long.class == toType) {
+ return Long.valueOf(value);
+ } else if (Float.class == toType) {
+ return Float.valueOf(value);
+ } else if (Double.class == toType) {
+ return Double.valueOf(value);
+ } else if (Character.class == toType) {
+ if (value.length() == 6 && value.startsWith("\\u")) {
+ int code = Integer.parseInt(value.substring(2), 16);
+ return (char)code;
+ } else if (value.length() == 1) {
+ return value.charAt(0);
+ } else {
+ throw new Exception("Invalid value for character type: " + value);
+ }
+ } else if (Byte.class == toType) {
+ return Byte.valueOf(value);
+ } else if (Enum.class.isAssignableFrom(toType)) {
+ return Enum.valueOf((Class<Enum>) toType, value);
+ } else {
+ return createObject(value, toType);
+ }
+ }
+
+ private static Object createObject(String value, Class type) throws Exception {
+ if (type.isInterface() || Modifier.isAbstract(type.getModifiers())) {
+ throw new Exception("Unable to convert value " + value + " to type " + type + ". Type " + type + " is an interface or an abstract class");
+ }
+ Constructor constructor = null;
+ try {
+ constructor = type.getConstructor(String.class);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Unable to convert to " + type);
+ }
+ try {
+ return constructor.newInstance(value);
+ } catch (Exception e) {
+ throw new Exception("Unable to convert ", getRealCause(e));
+ }
+ }
+
+ private static Throwable getRealCause(Throwable t) {
+ if (t instanceof InvocationTargetException && t.getCause() != null) {
+ return t.getCause();
+ }
+ return t;
+ }
+
+ private Object convertToCollection(Object obj, ReifiedType type) throws Exception {
+ ReifiedType valueType = type.getActualTypeArgument(0);
+ Collection newCol = (Collection) getCollection(toClass(type)).newInstance();
+ if (obj.getClass().isArray()) {
+ for (int i = 0; i < Array.getLength(obj); i++) {
+ try {
+ newCol.add(convert(Array.get(obj, i), valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting array element)", t);
+ }
+ }
+ } else {
+ for (Object item : (Collection) obj) {
+ try {
+ newCol.add(convert(item, valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting collection entry)", t);
+ }
+ }
+ }
+ return newCol;
+ }
+
+ private Object convertToDictionary(Object obj, ReifiedType type) throws Exception {
+ ReifiedType keyType = type.getActualTypeArgument(0);
+ ReifiedType valueType = type.getActualTypeArgument(1);
+ Dictionary newDic = new Hashtable();
+ if (obj instanceof Dictionary) {
+ Dictionary dic = (Dictionary) obj;
+ for (Enumeration keyEnum = dic.keys(); keyEnum.hasMoreElements();) {
+ Object key = keyEnum.nextElement();
+ try {
+ newDic.put(convert(key, keyType), convert(dic.get(key), valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting map entry)", t);
+ }
+ }
+ } else {
+ for (Map.Entry e : ((Map<Object,Object>) obj).entrySet()) {
+ try {
+ newDic.put(convert(e.getKey(), keyType), convert(e.getValue(), valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting map entry)", t);
+ }
+ }
+ }
+ return newDic;
+ }
+
+ private Object convertToMap(Object obj, ReifiedType type) throws Exception {
+ ReifiedType keyType = type.getActualTypeArgument(0);
+ ReifiedType valueType = type.getActualTypeArgument(1);
+ Map newMap = (Map) getMap(toClass(type)).newInstance();
+ if (obj instanceof Dictionary) {
+ Dictionary dic = (Dictionary) obj;
+ for (Enumeration keyEnum = dic.keys(); keyEnum.hasMoreElements();) {
+ Object key = keyEnum.nextElement();
+ try {
+ newMap.put(convert(key, keyType), convert(dic.get(key), valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting map entry)", t);
+ }
+ }
+ } else {
+ for (Map.Entry e : ((Map<Object,Object>) obj).entrySet()) {
+ try {
+ newMap.put(convert(e.getKey(), keyType), convert(e.getValue(), valueType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting map entry)", t);
+ }
+ }
+ }
+ return newMap;
+ }
+
+ private Object convertToArray(Object obj, ReifiedType type) throws Exception {
+ if (obj instanceof Collection) {
+ obj = ((Collection) obj).toArray();
+ }
+ if (!obj.getClass().isArray()) {
+ throw new Exception("Unable to convert from " + obj + " to " + type);
+ }
+ ReifiedType componentType;
+ if (type.size() > 0) {
+ componentType = type.getActualTypeArgument(0);
+ } else {
+ componentType = new GenericType(type.getRawClass().getComponentType());
+ }
+ Object array = Array.newInstance(toClass(componentType), Array.getLength(obj));
+ for (int i = 0; i < Array.getLength(obj); i++) {
+ try {
+ Array.set(array, i, convert(Array.get(obj, i), componentType));
+ } catch (Exception t) {
+ throw new Exception("Unable to convert from " + obj + " to " + type + "(error converting array element)", t);
+ }
+ }
+ return array;
+ }
+
+ public static boolean isAssignable(Object source, ReifiedType target) {
+ return source == null
+ || (target.size() == 0
+ && unwrap(target.getRawClass()).isAssignableFrom(unwrap(source.getClass())));
+ }
+
+ private static Class unwrap(Class c) {
+ Class u = primitives.get(c);
+ return u != null ? u : c;
+ }
+
+ private static Class getMap(Class type) {
+ if (hasDefaultConstructor(type)) {
+ return type;
+ } else if (SortedMap.class.isAssignableFrom(type)) {
+ return TreeMap.class;
+ } else if (ConcurrentMap.class.isAssignableFrom(type)) {
+ return ConcurrentHashMap.class;
+ } else {
+ return LinkedHashMap.class;
+ }
+ }
+
+ private static Class getCollection(Class type) {
+ if (hasDefaultConstructor(type)) {
+ return type;
+ } else if (SortedSet.class.isAssignableFrom(type)) {
+ return TreeSet.class;
+ } else if (Set.class.isAssignableFrom(type)) {
+ return LinkedHashSet.class;
+ } else if (List.class.isAssignableFrom(type)) {
+ return ArrayList.class;
+ } else if (Queue.class.isAssignableFrom(type)) {
+ return LinkedList.class;
+ } else {
+ return ArrayList.class;
+ }
+ }
+
+ private static boolean hasDefaultConstructor(Class type) {
+ if (!Modifier.isPublic(type.getModifiers())) {
+ return false;
+ }
+ if (Modifier.isAbstract(type.getModifiers())) {
+ return false;
+ }
+ Constructor[] constructors = type.getConstructors();
+ for (Constructor constructor : constructors) {
+ if (Modifier.isPublic(constructor.getModifiers()) &&
+ constructor.getParameterTypes().length == 0) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ private static final Map<Class, Class> primitives;
+ static {
+ primitives = new HashMap<Class, Class>();
+ primitives.put(byte.class, Byte.class);
+ primitives.put(short.class, Short.class);
+ primitives.put(char.class, Character.class);
+ primitives.put(int.class, Integer.class);
+ primitives.put(long.class, Long.class);
+ primitives.put(float.class, Float.class);
+ primitives.put(double.class, Double.class);
+ primitives.put(boolean.class, Boolean.class);
+ }
+
+ private Class toClass(ReifiedType type) {
+ return type.getRawClass();
+ }
+
+}
Added: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/GenericType.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/GenericType.java?rev=790958&view=auto
==============================================================================
--- felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/GenericType.java (added)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/GenericType.java Fri Jul 3 16:07:10 2009
@@ -0,0 +1,195 @@
+/**
+ *
+ * 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.converter;
+
+import java.lang.reflect.Array;
+import java.lang.reflect.GenericArrayType;
+import java.lang.reflect.ParameterizedType;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.lang.reflect.WildcardType;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.osgi.framework.Bundle;
+import org.apache.felix.gogo.commands.converter.ReifiedType;
+
+public class GenericType extends ReifiedType {
+
+ private static final GenericType[] EMPTY = new GenericType[0];
+
+ private static final Map<String, Class> primitiveClasses = new HashMap<String, Class>();
+
+ static {
+ primitiveClasses.put("int", int.class);
+ primitiveClasses.put("short", short.class);
+ primitiveClasses.put("long", long.class);
+ primitiveClasses.put("byte", byte.class);
+ primitiveClasses.put("char", char.class);
+ primitiveClasses.put("float", float.class);
+ primitiveClasses.put("double", double.class);
+ primitiveClasses.put("boolean", boolean.class);
+ }
+
+ private GenericType[] parameters;
+
+ public GenericType(Type type) {
+ this(getConcreteClass(type), parametersOf(type));
+ }
+
+ public GenericType(Class clazz, GenericType... parameters) {
+ super(clazz);
+ this.parameters = parameters;
+ }
+
+ public static GenericType parse(String type, Object loader) throws ClassNotFoundException, IllegalArgumentException {
+ type = type.trim();
+ // Check if this is an array
+ if (type.endsWith("[]")) {
+ GenericType t = parse(type.substring(0, type.length() - 2), loader);
+ return new GenericType(Array.newInstance(t.getRawClass(), 0).getClass(), t);
+ }
+ // Check if this is a generic
+ int genericIndex = type.indexOf('<');
+ if (genericIndex > 0) {
+ if (!type.endsWith(">")) {
+ throw new IllegalArgumentException("Can not load type: " + type);
+ }
+ GenericType base = parse(type.substring(0, genericIndex), loader);
+ String[] params = type.substring(genericIndex + 1, type.length() - 1).split(",");
+ GenericType[] types = new GenericType[params.length];
+ for (int i = 0; i < params.length; i++) {
+ types[i] = parse(params[i], loader);
+ }
+ return new GenericType(base.getRawClass(), types);
+ }
+ // Primitive
+ if (primitiveClasses.containsKey(type)) {
+ return new GenericType(primitiveClasses.get(type));
+ }
+ // Class
+ if (loader instanceof ClassLoader) {
+ return new GenericType(((ClassLoader) loader).loadClass(type));
+ } else if (loader instanceof Bundle) {
+ return new GenericType(((Bundle) loader).loadClass(type));
+ } else {
+ throw new IllegalArgumentException("Unsupported loader: " + loader);
+ }
+ }
+
+ @Override
+ public ReifiedType getActualTypeArgument(int i) {
+ if (parameters.length == 0) {
+ return super.getActualTypeArgument(i);
+ }
+ return parameters[i];
+ }
+
+ @Override
+ public int size() {
+ return parameters.length;
+ }
+
+ @Override
+ public String toString() {
+ Class cl = getRawClass();
+ if (cl.isArray()) {
+ if (parameters.length > 0) {
+ return parameters[0].toString() + "[]";
+ } else {
+ return cl.getComponentType().getName() + "[]";
+ }
+ }
+ if (parameters.length > 0) {
+ StringBuilder sb = new StringBuilder();
+ sb.append(cl.getName());
+ sb.append("<");
+ for (int i = 0; i < parameters.length; i++) {
+ if (i > 0) {
+ sb.append(",");
+ }
+ sb.append(parameters[i].toString());
+ }
+ sb.append(">");
+ return sb.toString();
+ }
+ return cl.getName();
+ }
+
+ static GenericType[] parametersOf(Type type ) {
+ if ( type instanceof Class ) {
+ Class clazz = (Class) type;
+ if (clazz.isArray()) {
+ GenericType t = new GenericType(clazz.getComponentType());
+ if (t.size() > 0) {
+ return new GenericType[] { t };
+ } else {
+ return EMPTY;
+ }
+ } else {
+ return EMPTY;
+ }
+ }
+ if ( type instanceof ParameterizedType ) {
+ ParameterizedType pt = (ParameterizedType) type;
+ Type [] parameters = pt.getActualTypeArguments();
+ GenericType[] gts = new GenericType[parameters.length];
+ for ( int i =0; i<gts.length; i++) {
+ gts[i] = new GenericType(parameters[i]);
+ }
+ return gts;
+ }
+ if ( type instanceof GenericArrayType ) {
+ return new GenericType[] { new GenericType(((GenericArrayType) type).getGenericComponentType()) };
+ }
+ throw new IllegalStateException();
+ }
+
+ static Class<?> getConcreteClass(Type type) {
+ Type ntype = collapse(type);
+ if ( ntype instanceof Class )
+ return (Class<?>) ntype;
+
+ if ( ntype instanceof ParameterizedType )
+ return getConcreteClass(collapse(((ParameterizedType)ntype).getRawType()));
+
+ throw new RuntimeException("Unknown type " + type );
+ }
+
+ static Type collapse(Type target) {
+ if (target instanceof Class || target instanceof ParameterizedType ) {
+ return target;
+ } else if (target instanceof TypeVariable) {
+ return collapse(((TypeVariable<?>) target).getBounds()[0]);
+ } else if (target instanceof GenericArrayType) {
+ Type t = collapse(((GenericArrayType) target)
+ .getGenericComponentType());
+ while ( t instanceof ParameterizedType )
+ t = collapse(((ParameterizedType)t).getRawType());
+ return Array.newInstance((Class<?>)t, 0).getClass();
+ } else if (target instanceof WildcardType) {
+ WildcardType wct = (WildcardType) target;
+ if (wct.getLowerBounds().length == 0)
+ return collapse(wct.getUpperBounds()[0]);
+ else
+ return collapse(wct.getLowerBounds()[0]);
+ }
+ throw new RuntimeException("Huh? " + target);
+ }
+
+}
Added: felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/ReifiedType.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/ReifiedType.java?rev=790958&view=auto
==============================================================================
--- felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/ReifiedType.java (added)
+++ felix/trunk/gogo/gogo.commands/src/main/java/org/apache/felix/gogo/commands/converter/ReifiedType.java Fri Jul 3 16:07:10 2009
@@ -0,0 +1,116 @@
+/*
+ * Copyright (c) OSGi Alliance (2008, 2009). All Rights Reserved.
+ *
+ * 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.felix.gogo.commands.converter;
+
+/**
+ * Provides access to a concrete type and its optional generic type arguments.
+ *
+ * Java 5 and later support generic types. These types consist of a raw class
+ * with type arguments. This class models such a <code>Type</code> class but
+ * ensures that the type is <em>reified</em>. Reification means that the Type
+ * graph associated with a Java 5 <code>Type</code> instance is traversed
+ * until the type becomes a concrete class. In Java 1.4 a class has no
+ * arguments. This concrete class implements the Reified Type for Java 1.4.
+ *
+ * In Java 1.4, this class works with non-generic types. In that cases, a
+ * Reified Type provides access to the class and has zero type arguments, though
+ * a subclass that provide type arguments should be respected. Blueprint
+ * extender implementations can subclass this class and provide access to the
+ * generics type graph if used in a conversion. Such a subclass must
+ * <em>reify<em> the different Java 5 <code>Type</code> instances into the
+ * reified form. That is, a form where the raw Class is available with its optional type arguments as Reified Types.
+ *
+ * @Immutable
+ */
+public class ReifiedType {
+ final static ReifiedType ALL = new ReifiedType(Object.class);
+
+ private final Class clazz;
+
+ /**
+ * Create a Reified Type for a raw Java class without any generic arguments.
+ * Subclasses can provide the optional generic argument information. Without
+ * subclassing, this instance has no type arguments.
+ *
+ * @param clazz
+ * The raw class of the Reified Type.
+ */
+ public ReifiedType(Class clazz) {
+ this.clazz = clazz;
+ }
+
+ /**
+ * Access to the raw class.
+ *
+ * The raw class represents the concrete class that is associated with a
+ * type declaration. This class could have been deduced from the generics
+ * type graph of the declaration. For example, in the following example:
+ *
+ * <pre>
+ * Map<String, Object> map;
+ * </pre>
+ *
+ * The raw class is the Map class.
+ *
+ * @return the collapsed raw class that represents this type.
+ */
+ public Class getRawClass() {
+ return clazz;
+ }
+
+ /**
+ * Access to a type argument.
+ *
+ * The type argument refers to a argument in a generic type declaration
+ * given by index <code>i</code>. This method returns a Reified Type that
+ * has Object as class when no generic type information is available. Any
+ * object is assignable to Object and therefore no conversion is then
+ * necessary, this is compatible with older Javas than 5. For this reason,
+ * the implementation in this class always returns the
+ * <code>Object<code> class, regardless of the given index.
+ *
+ * This method should be overridden by a subclass that provides access to
+ * the generic information.
+ *
+ * For example, in the following example:
+ *
+ * <pre>
+ * Map<String, Object> map;
+ * </pre>
+ *
+ * The type argument 0 is <code>String</code>, and type argument 1 is
+ * <code>Object</code>.
+ *
+ * @param i
+ * The index of the type argument
+ * @return <code>ReifiedType(Object.class)<code>, subclasses must override this and return the generic argument at index <code>i</code>
+ */
+ public ReifiedType getActualTypeArgument(int i) {
+ return ALL;
+ }
+
+ /**
+ * Return the number of type arguments.
+ *
+ * This method should be overridden by a subclass to support Java 5 types.
+ *
+ * @return 0, subclasses must override this and return the number of generic
+ * arguments
+ */
+ public int size() {
+ return 0;
+ }
+}
Added: felix/trunk/gogo/gogo.commands/src/test/java/org/apache/felix/gogo/commands/TestCommands.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.commands/src/test/java/org/apache/felix/gogo/commands/TestCommands.java?rev=790958&view=auto
==============================================================================
--- felix/trunk/gogo/gogo.commands/src/test/java/org/apache/felix/gogo/commands/TestCommands.java (added)
+++ felix/trunk/gogo/gogo.commands/src/test/java/org/apache/felix/gogo/commands/TestCommands.java Fri Jul 3 16:07:10 2009
@@ -0,0 +1,87 @@
+/*
+ * 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.util.List;
+import java.util.Collections;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+import org.osgi.service.command.CommandSession;
+import org.apache.felix.gogo.runtime.shell.Context;
+import org.apache.felix.gogo.commands.basic.SimpleCommand;
+
+public class TestCommands extends TestCase {
+
+
+ public void testCommand() throws Exception {
+ Context c= new Context();
+ c.addCommand("my-action", new SimpleCommand(MyAction.class));
+
+ // Test help
+ c.execute("my-action --help");
+
+ // Test required argument
+ try
+ {
+ c.execute("my-action");
+ fail("Action should have thrown an exception because of a missing argument");
+ }
+ catch (IllegalArgumentException e)
+ {
+ }
+
+ // Test required argument
+ assertEquals(Arrays.asList(3), c.execute("my-action 3"));
+
+ // Test required argument
+ assertEquals(Arrays.asList(3), c.execute("my-action 3"));
+
+ // Test required argument
+ assertEquals(Arrays.asList(3, 5), c.execute("my-action 3 5"));
+
+ // Test option
+ assertEquals(Arrays.asList(4), c.execute("my-action -i 3"));
+
+ // Test option alias
+ assertEquals(Arrays.asList(4), c.execute("my-action --increment 3"));
+ }
+
+ @Command(scope = "test", name = "my-action", description = "My Action")
+ public static class MyAction implements Action
+ {
+
+ @Option(name = "-i", aliases = { "--increment" }, description = "First option")
+ private boolean increment;
+
+ @Argument(name = "ids", description = "Bundle ids", required = true, multiValued = true)
+ private List<Integer> ids;
+
+ public Object execute(CommandSession session) throws Exception {
+ if (increment)
+ {
+ for (int i = 0; i < ids.size(); i++)
+ {
+ ids.set(i, ids.get(i) + 1);
+ }
+ }
+ return ids;
+ }
+ }
+}
Modified: felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java?rev=790958&r1=790957&r2=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java (original)
+++ felix/trunk/gogo/gogo.console/src/main/java/org/apache/felix/gogo/console/stdio/StdioConsole.java Fri Jul 3 16:07:10 2009
@@ -19,7 +19,6 @@
package org.apache.felix.gogo.console.stdio;
import org.osgi.service.command.CommandProcessor;
-import org.osgi.service.component.ComponentContext;
public class StdioConsole extends Thread
{
Modified: felix/trunk/gogo/gogo.runtime/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.runtime/pom.xml?rev=790958&r1=790957&r2=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.runtime/pom.xml (original)
+++ felix/trunk/gogo/gogo.runtime/pom.xml Fri Jul 3 16:07:10 2009
@@ -59,7 +59,6 @@
org.osgi.service.threadio; version=1.0.0
</Export-Package>
<Import-Package>
- org.osgi.service.component*; resolution:=optional,
org.osgi.service.log*; resolution:=optional,
org.osgi.service.packageadmin*; resolution:=optional,
org.osgi.service.startlevel*; resolution:=optional,
@@ -69,6 +68,7 @@
<Bundle-SymbolicName>${pom.artifactId}</Bundle-SymbolicName>
<Bundle-Vendor>The Apache Software Foundation</Bundle-Vendor>
<Bundle-Activator>org.apache.felix.gogo.runtime.Activator</Bundle-Activator>
+ <_versionpolicy>[$(version;==;$(@)),$(version;+;$(@)))</_versionpolicy>
</instructions>
</configuration>
</plugin>
Modified: felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/osgi/OSGiShell.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/osgi/OSGiShell.java?rev=790958&r1=790957&r2=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/osgi/OSGiShell.java (original)
+++ felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/osgi/OSGiShell.java Fri Jul 3 16:07:10 2009
@@ -26,7 +26,6 @@
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.service.command.Converter;
-import org.osgi.service.component.ComponentContext;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.threadio.ThreadIO;
@@ -35,16 +34,6 @@
Bundle bundle;
OSGiCommands commands;
- protected void activate(ComponentContext context) throws Exception
- {
- this.bundle = context.getBundleContext().getBundle();
- if (threadIO == null)
- {
- threadIO = (ThreadIO) context.locateService("x");
- }
- start();
- }
-
public void start() throws Exception
{
commands = new OSGiCommands(bundle);
@@ -84,11 +73,6 @@
}
}
- protected void deactivate(ComponentContext context)
- {
- System.out.println("Deactivating");
- }
-
public Object get(String name)
{
if (bundle.getBundleContext() != null)
Modified: felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java?rev=790958&r1=790957&r2=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java (original)
+++ felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Closure.java Fri Jul 3 16:07:10 2009
@@ -235,7 +235,7 @@
{
return false;
}
- return seq;
+ return result;
}
}
Modified: felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java?rev=790958&r1=790957&r2=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java (original)
+++ felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/shell/Parser.java Fri Jul 3 16:07:10 2009
@@ -28,7 +28,7 @@
int current = 0;
CharSequence text;
boolean escaped;
- static final String SPECIAL = "<;|{[\"'$'`(=";
+ static final String SPECIAL = "<;|{[\"'$`(=";
public Parser(CharSequence program)
{
@@ -71,24 +71,29 @@
char peek()
{
+ return peek(false);
+ }
+
+ char peek(boolean increment)
+ {
escaped = false;
if (eof())
{
return 0;
}
- char c = text.charAt(current);
+ int last = current;
+ char c = text.charAt(current++);
if (c == '\\')
{
escaped = true;
- ++current;
if (eof())
{
throw new RuntimeException("Eof found after \\"); // derek
}
- c = text.charAt(current);
+ c = text.charAt(current++);
switch (c)
{
@@ -113,12 +118,16 @@
break;
case 'u':
c = unicode();
+ current += 4;
break;
default:
// We just take the next character literally
// but have the escaped flag set, important for {},[] etc
}
}
+ if (!increment) {
+ current = last;
+ }
return c;
}
@@ -200,7 +209,6 @@
}
next();
}
-
return text.subSequence(start, current);
}
else
@@ -215,59 +223,45 @@
int start = current;
char c = next();
- switch (c)
- {
- case '{':
- return text.subSequence(start, find('}', '{'));
- case '(':
- return text.subSequence(start, find(')', '('));
- case '[':
- return text.subSequence(start, find(']', '['));
- case '"':
- return text.subSequence(start + 1, quote('"'));
- case '\'':
- return text.subSequence(start + 1, quote('\''));
- case '<':
- return text.subSequence(start, find('>', '<'));
- case '$':
- value();
- return text.subSequence(start, current);
- }
-
- if (Character.isJavaIdentifierPart(c))
- {
- // Some identifier or number
- while (!eof())
+ if (!escaped) {
+ switch (c)
{
- c = peek();
- if (c != ':' && !Character.isJavaIdentifierPart(c) && c != '.')
- {
- break;
- }
- next();
+ case '{':
+ return text.subSequence(start, find('}', '{'));
+ case '(':
+ return text.subSequence(start, find(')', '('));
+ case '[':
+ return text.subSequence(start, find(']', '['));
+ case '"':
+ return text.subSequence(start + 1, quote('"'));
+ case '\'':
+ return text.subSequence(start + 1, quote('\''));
+ case '<':
+ return text.subSequence(start, find('>', '<'));
+ case '$':
+ value();
+ return text.subSequence(start, current);
+ case '=':
+ return text.subSequence(start, current);
}
}
- else
+
+ // Some identifier or number
+ while (!eof())
{
- // Operator, repeat while in operator class
- while (!eof())
+ c = peek();
+ if ((!escaped && SPECIAL.indexOf(c) >= 0) || Character.isWhitespace(c))
{
- c = peek();
- if (Character.isWhitespace(c) || Character.isJavaIdentifierPart(c))
- {
- break;
- }
+ break;
}
+ next();
}
-
return text.subSequence(start, current);
}
char next()
{
- char c = peek();
- current++;
- return c;
+ return peek(true);
}
char unicode()
Modified: felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java?rev=790958&r1=790957&r2=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java (original)
+++ felix/trunk/gogo/gogo.runtime/src/main/java/org/apache/felix/gogo/runtime/threadio/ThreadIOImpl.java Fri Jul 3 16:07:10 2009
@@ -19,7 +19,6 @@
// DWB20: ThreadIO should check and reset IO if something (e.g. jetty) overrides
package org.apache.felix.gogo.runtime.threadio;
-import org.osgi.service.component.ComponentContext;
import org.osgi.service.threadio.ThreadIO;
import java.io.InputStream;
@@ -34,23 +33,6 @@
ThreadInputStream in = new ThreadInputStream(System.in);
ThreadLocal<Marker> current = new ThreadLocal<Marker>();
- protected void activate(ComponentContext context)
- {
- start();
- }
-
- protected void deactivate()
- {
- stop();
- }
-
- public void stop()
- {
- System.setErr(err.dflt);
- System.setOut(out.dflt);
- System.setIn(in.dflt);
- }
-
public void start()
{
if (System.out instanceof ThreadPrintStream)
@@ -62,6 +44,13 @@
System.setErr(err);
}
+ public void stop()
+ {
+ System.setErr(err.dflt);
+ System.setOut(out.dflt);
+ System.setIn(in.dflt);
+ }
+
private void checkIO()
{ // derek
if (System.in != in)
Modified: felix/trunk/gogo/gogo.runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/gogo.runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java?rev=790958&r1=790957&r2=790958&view=diff
==============================================================================
--- felix/trunk/gogo/gogo.runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java (original)
+++ felix/trunk/gogo/gogo.runtime/src/test/java/org/apache/felix/gogo/runtime/shell/TestParser.java Fri Jul 3 16:07:10 2009
@@ -35,6 +35,15 @@
{
int beentheredonethat = 0;
+ public void testScope() throws Exception
+ {
+ Context c= new Context();
+ c.addCommand("echo", this);
+ c.addCommand("capture", this);
+ assertEquals("$a", c.execute("test:echo \\$a | capture"));
+ assertEquals("file://poo", c.execute("test:echo file://poo|capture"));
+ }
+
public void testPipe() throws Exception
{
Context c = new Context();
@@ -98,6 +107,7 @@
CharSequence cs = parser.messy();
assertEquals("a|b;c", cs.toString());
assertEquals("a|b;c", new Parser(cs).unescape());
+ assertEquals("$a", new Parser("\\$a").unescape());
}
Modified: felix/trunk/gogo/pom.xml
URL: http://svn.apache.org/viewvc/felix/trunk/gogo/pom.xml?rev=790958&r1=790957&r2=790958&view=diff
==============================================================================
--- felix/trunk/gogo/pom.xml (original)
+++ felix/trunk/gogo/pom.xml Fri Jul 3 16:07:10 2009
@@ -27,6 +27,7 @@
<modelVersion>4.0.0</modelVersion>
<packaging>pom</packaging>
<name>Apache Felix Gogo Shell</name>
+ <description>Apache Felix Gogo Shell</description>
<groupId>org.apache.felix.gogo</groupId>
<artifactId>gogo</artifactId>
<version>1.0.0-SNAPSHOT</version>
@@ -35,6 +36,7 @@
<module>gogo.runtime</module>
<module>gogo.launcher</module>
<module>gogo.console</module>
+ <module>gogo.commands</module>
</modules>
<dependencyManagement>