You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@karaf.apache.org by gn...@apache.org on 2016/10/19 09:28:17 UTC

[1/3] karaf git commit: [KARAF-397] Allow completion of non Karaf based osgi commands [KARAF-2454] Portable way to make custom shell commands

Repository: karaf
Updated Branches:
  refs/heads/master 42ef36477 -> f1dd4a94c


http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java b/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
index 46de633..642d8bb 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImpl.java
@@ -16,11 +16,11 @@
  */
 package org.apache.karaf.shell.security.impl;
 
-import org.apache.felix.gogo.api.CommandSessionListener;
 import org.apache.felix.gogo.runtime.CommandProcessorImpl;
 import org.apache.felix.gogo.runtime.CommandProxy;
 import org.apache.felix.gogo.runtime.activator.Activator;
 import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.CommandSessionListener;
 import org.apache.felix.service.command.Converter;
 import org.apache.felix.service.command.Function;
 import org.apache.felix.service.threadio.ThreadIO;
@@ -34,7 +34,6 @@ import org.osgi.util.tracker.ServiceTracker;
 
 import javax.security.auth.Subject;
 
-import java.nio.file.attribute.UserPrincipal;
 import java.security.AccessControlContext;
 import java.security.AccessController;
 import java.util.ArrayList;
@@ -175,10 +174,10 @@ public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
     }
 
     private ServiceTracker<CommandSessionListener, CommandSessionListener> trackListeners(BundleContext context) {
-        return new ServiceTracker<CommandSessionListener, CommandSessionListener>(context, CommandSessionListener.class.getName(), null) {
+        return new ServiceTracker<CommandSessionListener, CommandSessionListener>(context, CommandSessionListener.class, null) {
             @Override
             public CommandSessionListener addingService(ServiceReference<CommandSessionListener> reference) {
-                CommandSessionListener listener = super.addingService(reference);
+                CommandSessionListener listener = context.getService(reference);
                 addListener(listener);
                 return listener;
             }
@@ -186,7 +185,7 @@ public class SecuredCommandProcessorImpl extends CommandProcessorImpl {
             @Override
             public void removedService(ServiceReference<CommandSessionListener> reference, CommandSessionListener service) {
                 removeListener(service);
-                super.removedService(reference, service);
+                context.ungetService(reference);
             }
         };
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/pom.xml
----------------------------------------------------------------------
diff --git a/shell/core/pom.xml b/shell/core/pom.xml
index 356029e..83b143f 100644
--- a/shell/core/pom.xml
+++ b/shell/core/pom.xml
@@ -143,7 +143,8 @@
                         <Export-Package>
                             org.apache.karaf.shell.api.*;version=${project.version},
                             org.apache.karaf.shell.support.*;version=${project.version},
-                            org.apache.felix.gogo.api
+                            org.apache.felix.service.command,
+                            org.apache.felix.service.threadio
                         </Export-Package>
                         <Private-Package>
                             org.apache.karaf.service.guard.tools,

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandWrapper.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandWrapper.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandWrapper.java
index 9488d8f..e1e7e7f 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandWrapper.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandWrapper.java
@@ -47,12 +47,7 @@ public class CommandWrapper implements Function {
             Object v = arguments.get(i);
             if (v instanceof Closure) {
                 final Closure closure = (Closure) v;
-                arguments.set(i, new org.apache.karaf.shell.api.console.Function() {
-                    @Override
-                    public Object execute(Session session, List<Object> arguments) throws Exception {
-                        return closure.execute(commandSession, arguments);
-                    }
-                });
+                arguments.set(i, (org.apache.karaf.shell.api.console.Function) (s, a) -> closure.execute(commandSession, a));
             }
         }
         return command.execute(session, arguments);

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
index 7318a4f..3a9dc22 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/ConsoleSessionImpl.java
@@ -33,22 +33,25 @@ import java.nio.file.Paths;
 import java.nio.file.PathMatcher;
 import java.util.ArrayList;
 import java.util.EnumSet;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
+import java.util.Set;
 import java.nio.file.attribute.BasicFileAttributes;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 import java.util.stream.Stream;
 
-import org.apache.felix.gogo.api.Job;
-import org.apache.felix.gogo.api.Job.Status;
+import org.apache.felix.gogo.jline.Shell;
 import org.apache.felix.gogo.runtime.CommandSessionImpl;
 import org.apache.felix.service.command.CommandProcessor;
 import org.apache.felix.service.command.CommandSession;
 import org.apache.felix.service.command.Converter;
 import org.apache.felix.service.command.Function;
+import org.apache.felix.service.command.Job;
+import org.apache.felix.service.command.Job.Status;
 import org.apache.felix.service.threadio.ThreadIO;
 import org.apache.karaf.shell.api.console.Command;
 import org.apache.karaf.shell.api.console.History;
@@ -62,11 +65,9 @@ import org.apache.karaf.shell.support.ShellUtil;
 import org.apache.karaf.shell.support.completers.FileCompleter;
 import org.apache.karaf.shell.support.completers.FileOrUriCompleter;
 import org.apache.karaf.shell.support.completers.UriCompleter;
-import org.jline.reader.EndOfFileException;
-import org.jline.reader.UserInterruptException;
+import org.jline.builtins.Completers;
+import org.jline.reader.*;
 import org.jline.reader.impl.LineReaderImpl;
-import org.jline.reader.impl.history.history.FileHistory;
-import org.jline.reader.impl.history.history.MemoryHistory;
 import org.jline.terminal.Terminal.Signal;
 import org.jline.terminal.impl.DumbTerminal;
 import org.slf4j.Logger;
@@ -78,6 +79,8 @@ public class ConsoleSessionImpl implements Session {
     public static final String SHELL_HISTORY_MAXSIZE = "karaf.shell.history.maxSize";
     public static final String PROMPT = "PROMPT";
     public static final String DEFAULT_PROMPT = "\u001B[1m${USER}\u001B[0m@${APPLICATION}(${SUBSHELL})> ";
+    public static final String RPROMPT = "RPROMPT";
+    public static final String DEFAULT_RPROMPT = null;
 
     private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleSessionImpl.class);
 
@@ -147,18 +150,11 @@ public class ConsoleSessionImpl implements Session {
                 ((CommandSessionImpl) session).getVariables());
 
         // History
-        final File file = getHistoryFile();
-        try {
-            file.getParentFile().mkdirs();
-            reader.setHistory(new FileHistory(file));
-        } catch (Exception e) {
-            LOGGER.error("Can not read history from file " + file + ". Using in memory history", e);
-        }
-        if (reader.getHistory() instanceof MemoryHistory) {
-            String maxSizeStr = System.getProperty(SHELL_HISTORY_MAXSIZE);
-            if (maxSizeStr != null) {
-                ((MemoryHistory) this.reader.getHistory()).setMaxSize(Integer.parseInt(maxSizeStr));
-            }
+        final Path file = getHistoryFile();
+        reader.setVariable(LineReader.HISTORY_FILE, file);
+        String maxSizeStr = System.getProperty(SHELL_HISTORY_MAXSIZE);
+        if (maxSizeStr != null) {
+            reader.setVariable(LineReader.HISTORY_SIZE, Integer.parseInt(maxSizeStr));
         }
         history = new HistoryWrapper(reader.getHistory());
 
@@ -171,9 +167,37 @@ public class ConsoleSessionImpl implements Session {
         registry.register(history);
 
         // Completers
-        CommandsCompleter completer = new CommandsCompleter(factory, this);
-        reader.setCompleter(completer);
-        registry.register(completer);
+        Completers.CompletionEnvironment env = new Completers.CompletionEnvironment() {
+            @Override
+            public Map<String, List<Completers.CompletionData>> getCompletions() {
+                return Shell.getCompletions(session);
+            }
+            @Override
+            public Set<String> getCommands() {
+                return Shell.getCommands(session);
+            }
+            @Override
+            public String resolveCommand(String command) {
+                return Shell.resolve(session, command);
+            }
+            @Override
+            public String commandName(String command) {
+                int idx = command.indexOf(':');
+                return idx >= 0 ? command.substring(idx + 1) : command;
+            }
+            @Override
+            public Object evaluate(LineReader reader, ParsedLine line, String func) throws Exception {
+                session.put(Shell.VAR_COMMAND_LINE, line);
+                return session.execute(func);
+            }
+        };
+        Completer builtinCompleter = new org.jline.builtins.Completers.Completer(env);
+        CommandsCompleter commandsCompleter = new CommandsCompleter(factory, this);
+        reader.setCompleter((rdr, line, candidates) -> {
+            builtinCompleter.complete(rdr, line, candidates);
+            commandsCompleter.complete(rdr, line, candidates);
+        });
+        registry.register(commandsCompleter);
         registry.register(new CommandNamesCompleter());
         registry.register(new FileCompleter());
         registry.register(new UriCompleter());
@@ -198,7 +222,11 @@ public class ConsoleSessionImpl implements Session {
         session.put("#LINES", (Function) (session, arguments) -> Integer.toString(terminal.getHeight()));
         session.put("#COLUMNS", (Function) (session, arguments) -> Integer.toString(terminal.getWidth()));
         session.put("pid", getPid());
-        session.currentDir(null);
+        session.put(Shell.VAR_COMPLETIONS, new HashMap<>());
+        session.put(Shell.VAR_READER, reader);
+        session.put(Shell.VAR_TERMINAL, reader.getTerminal());
+        session.put(CommandSession.OPTION_NO_GLOB, Boolean.TRUE);
+        session.currentDir(Paths.get(System.getProperty("user.dir")).toAbsolutePath().normalize());
 
         reader.setHighlighter(new org.apache.felix.gogo.jline.Highlighter(session));
         reader.setParser(new KarafParser(this));
@@ -210,9 +238,9 @@ public class ConsoleSessionImpl implements Session {
      *
      * @return the history file
      */
-    protected File getHistoryFile() {
-        String defaultHistoryPath = new File(System.getProperty("user.home"), ".karaf/karaf.history").toString();
-        return new File(System.getProperty("karaf.history", defaultHistoryPath));
+    protected Path getHistoryFile() {
+        String defaultHistoryPath = new File(System.getProperty("user.home"), ".karaf/karaf41.history").toString();
+        return Paths.get(System.getProperty("karaf.history", defaultHistoryPath));
     }
 
     @Override
@@ -239,11 +267,7 @@ public class ConsoleSessionImpl implements Session {
             return;
         }
 //        out.println();
-        try {
-            reader.getHistory().flush();
-        } catch (IOException e) {
-            // ignore
-        }
+        reader.getHistory().save();
 
         running = false;
         if (thread != Thread.currentThread()) {
@@ -307,7 +331,7 @@ public class ConsoleSessionImpl implements Session {
                     reading.set(true);
                     String command;
                     try {
-                        command = reader.readLine(getPrompt());
+                        command = reader.readLine(getPrompt(), getRPrompt(), null, null);
                     } finally {
                         reading.set(false);
                     }
@@ -554,25 +578,39 @@ public class ConsoleSessionImpl implements Session {
     }
 
     protected String getPrompt() {
+        return doGetPrompt(PROMPT, DEFAULT_PROMPT);
+    }
+
+    protected String getRPrompt() {
+        return doGetPrompt(RPROMPT, DEFAULT_RPROMPT);
+    }
+
+    protected String doGetPrompt(String var, String def) {
         try {
             String prompt;
             try {
-                Object p = session.get(PROMPT);
+                Object p = session.get(var);
                 if (p != null) {
                     prompt = p.toString();
                 } else {
-                    Properties properties = Branding.loadBrandingProperties(terminal);
-                    if (properties.getProperty("prompt") != null) {
-                        prompt = properties.getProperty("prompt");
-                        // we put the PROMPT in ConsoleSession to avoid to read
-                        // the properties file each time.
-                        session.put(PROMPT, prompt);
+                    var = var.toLowerCase();
+                    p = session.get(var);
+                    if (p != null) {
+                        prompt = p.toString();
                     } else {
-                        prompt = DEFAULT_PROMPT;
+                        Properties properties = Branding.loadBrandingProperties(terminal);
+                        if (properties.getProperty(var) != null) {
+                            prompt = properties.getProperty(var);
+                            // we put the PROMPT in ConsoleSession to avoid to read
+                            // the properties file each time.
+                            session.put(var, prompt);
+                        } else {
+                            prompt = def;
+                        }
                     }
                 }
             } catch (Throwable t) {
-                prompt = DEFAULT_PROMPT;
+                prompt = def;
             }
             Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(prompt);
             while (matcher.find()) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HistoryWrapper.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HistoryWrapper.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HistoryWrapper.java
index ef21593..25f0dff 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HistoryWrapper.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HistoryWrapper.java
@@ -30,7 +30,7 @@ public class HistoryWrapper implements History {
 
     @Override
     public void clear() {
-        history.clear();
+        history.purge();
     }
 
     public int first() {

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java
index 8ccf2b4..840e23a 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/SessionFactoryImpl.java
@@ -24,11 +24,12 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
-import java.util.function.BiConsumer;
 
 import org.apache.felix.gogo.jline.Builtin;
+import org.apache.felix.gogo.jline.Posix;
+import org.apache.felix.gogo.jline.Procedural;
 import org.apache.felix.gogo.runtime.CommandProcessorImpl;
-import org.apache.felix.gogo.runtime.CommandProxy;
+import org.apache.felix.gogo.runtime.Reflective;
 import org.apache.felix.service.command.CommandSession;
 import org.apache.felix.service.command.Function;
 import org.apache.felix.service.threadio.ThreadIO;
@@ -47,7 +48,7 @@ public class SessionFactoryImpl extends RegistryImpl implements SessionFactory,
 
     final CommandProcessorImpl commandProcessor;
     final ThreadIO threadIO;
-    final Map<String, SubShellCommand> subshells = new HashMap<String, SubShellCommand>();
+    final Map<String, SubShellCommand> subshells = new HashMap<>();
     boolean closed;
 
     public SessionFactoryImpl(ThreadIO threadIO) {
@@ -56,12 +57,24 @@ public class SessionFactoryImpl extends RegistryImpl implements SessionFactory,
         commandProcessor = new CommandProcessorImpl(threadIO);
         register(new ExitCommand());
         new HelpCommand(this);
-        register(new JobCommand("jobs", "List shell jobs", (session, args) -> new Builtin().jobs(session, args)));
-        register(new JobCommand("fg", "Put job in foreground", (session, args) -> new Builtin().fg(session, args)));
-        register(new JobCommand("bg", "Put job in background", (session, args) -> new Builtin().bg(session, args)));
-        register(new ProcessorCommand("addCommand", "Add a command"));
-        register(new ProcessorCommand("removeCommand", "Remove a command"));
-        register(new ProcessorCommand("eval", "Evaluate"));
+        register(new ShellCommand("addCommand", "Add a command", commandProcessor, "addCommand"));
+        register(new ShellCommand("removeCommand", "Remove a command", commandProcessor, "removeCommand"));
+        register(new ShellCommand("eval", "Evaluate", commandProcessor, "eval"));
+
+        Builtin builtin = new Builtin();
+        for (String name : new String[]{"format", "getopt", "new", "set", "tac", "type", "jobs", "fg", "bg", "keymap", "setopt", "unsetopt", "complete", "history", "widget", "__files", "__directories", "__usage_completion"}) {
+            register(new ShellCommand(name, null, builtin, name));
+        }
+
+        Procedural procedural = new Procedural();
+        for (String name : new String[]{"each", "if", "not", "throw", "try", "until", "while", "break", "continue"}) {
+            register(new ShellCommand(name, null, procedural, name));
+        }
+
+        Posix posix = new Posix(commandProcessor);
+        for (String name : new String[]{"cat", "echo", "grep", "sort", "sleep", "cd", "pwd", "ls", "less", "watch", "nano", "head", "tail", "clear", "wc", "date"}) {
+            register(new ShellCommand(name, null, posix, name));
+        }
     }
 
     public CommandProcessorImpl getCommandProcessor() {
@@ -151,62 +164,50 @@ public class SessionFactoryImpl extends RegistryImpl implements SessionFactory,
         }
     }
 
-    private class JobCommand implements Command {
+    private static class ShellCommand implements Command {
         private final String name;
         private final String desc;
-        private final BiConsumer<CommandSession, String[]> consumer;
+        private final Executable consumer;
 
-        public JobCommand(String name, String desc, BiConsumer<CommandSession, String[]> consumer) {
-            this.name = name;
-            this.desc = desc;
-            this.consumer = consumer;
+        interface Executable {
+            Object execute(CommandSession session, List<Object> args) throws Exception;
         }
 
-        @Override
-        public String getScope() {
-            return "shell";
+        interface ExecutableStr {
+            void execute(CommandSession session, String[] args) throws Exception;
         }
 
-        @Override
-        public String getName() {
-            return name;
+        public ShellCommand(String name, String desc, Executable consumer) {
+            this.name = name;
+            this.desc = desc;
+            this.consumer = consumer;
         }
 
-        @Override
-        public String getDescription() {
-            return desc;
+        public ShellCommand(String name, String desc, ExecutableStr consumer) {
+            this(name, desc, wrap(consumer));
         }
 
-        @Override
-        public Completer getCompleter(boolean scoped) {
-            return null;
+        public ShellCommand(String name, String desc, Object target, String method) {
+            this(name, desc, wrap(target, method));
         }
 
-        @Override
-        public Parser getParser() {
-            return null;
+        private static Executable wrap(Object target, String name) {
+            return (session, args) -> Reflective.invoke(session, target, name, args);
         }
 
-        @Override
-        public Object execute(Session session, List<Object> arguments) throws Exception {
-            CommandSession cmdSession = (CommandSession) session.get(".commandSession");
-            String[] args = new String[arguments.size()];
-            for (int i = 0; i < args.length; i++) {
-                args[i] = Objects.toString(arguments.get(i));
-            }
-            consumer.accept(cmdSession, args);
-            return null;
+        private static Executable wrap(ExecutableStr command) {
+            return (session, args) -> {
+                command.execute(session, asStringArray(args));
+                return null;
+            };
         }
-    }
-
-    private class ProcessorCommand implements Command {
-
-        private final String name;
-        private final String desc;
 
-        public ProcessorCommand(String name, String desc) {
-            this.name = name;
-            this.desc = desc;
+        private static String[] asStringArray(List<Object> args) {
+            String[] argv = new String[args.size()];
+            for (int i = 0; i < argv.length; i++) {
+                argv[i] = Objects.toString(args.get(i));
+            }
+            return argv;
         }
 
         @Override
@@ -237,9 +238,8 @@ public class SessionFactoryImpl extends RegistryImpl implements SessionFactory,
         @Override
         public Object execute(Session session, List<Object> arguments) throws Exception {
             CommandSession cmdSession = (CommandSession) session.get(".commandSession");
-            return new CommandProxy(commandProcessor, name).execute(cmdSession, arguments);
+            return consumer.execute(cmdSession, arguments);
         }
-
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/Activator.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/Activator.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/Activator.java
index 5f7e5ba..d55019f 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/Activator.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/Activator.java
@@ -55,6 +55,8 @@ public class Activator implements BundleActivator {
 
     ServiceTracker<CommandLoggingFilter, CommandLoggingFilter> filterTracker;
 
+    CommandTracker commandTracker;
+
     @Override
     public void start(final BundleContext context) throws Exception {
         threadIO = new ThreadIOImpl();
@@ -104,6 +106,9 @@ public class Activator implements BundleActivator {
         actionExtender = new CommandExtender(sessionFactory);
         actionExtender.start(context);
 
+        commandTracker = new CommandTracker(sessionFactory, context);
+        commandTracker.open();
+
         if (Boolean.parseBoolean(context.getProperty(START_CONSOLE))) {
             localConsoleManager = new LocalConsoleManager(context, sessionFactory);
             localConsoleManager.start();
@@ -121,6 +126,7 @@ public class Activator implements BundleActivator {
         }
         sessionFactory.stop();
         actionExtender.stop(context);
+        commandTracker.close();
         threadIO.stop();
         if (eventAdminListener != null) {
             eventAdminListener.close();

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/CommandTracker.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/CommandTracker.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/CommandTracker.java
new file mode 100644
index 0000000..c631017
--- /dev/null
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/CommandTracker.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.karaf.shell.impl.console.osgi;
+
+import org.apache.felix.gogo.runtime.CommandProxy;
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.Function;
+import org.apache.karaf.shell.api.console.*;
+import org.osgi.framework.*;
+import org.osgi.util.tracker.ServiceTracker;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class CommandTracker extends ServiceTracker<Object, List<Command>> {
+
+    final SessionFactory sessionFactory;
+
+    public CommandTracker(SessionFactory sessionFactory, BundleContext context) throws InvalidSyntaxException{
+        super(context, createFilter(context), null);
+        this.sessionFactory = sessionFactory;
+    }
+
+    static private Filter createFilter(BundleContext context) throws InvalidSyntaxException {
+        return context.createFilter(String.format("(&(%s=*)(%s=*)(!(%s=%s))(!(%s=%s)))",
+                CommandProcessor.COMMAND_SCOPE,
+                CommandProcessor.COMMAND_FUNCTION,
+                Constants.OBJECTCLASS,
+                "org.apache.felix.gogo.commands.CommandWithAction",
+                Constants.OBJECTCLASS,
+                "org.apache.karaf.shell.commands.CommandWithAction"));
+    }
+
+    @Override
+    public List<Command> addingService(final ServiceReference<Object> reference) {
+        final String scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE).toString();
+        final Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
+
+        final List<String> names = new ArrayList<>();
+        if (function.getClass().isArray()) {
+            for (final Object f : ((Object[]) function)) {
+                names.add(f.toString());
+            }
+        } else {
+            names.add(function.toString());
+        }
+
+        List<Command> commands = new ArrayList<>();
+        for (String name : names) {
+            final Function target = new CommandProxy(context, reference, name);
+            Command command = new Command() {
+                @Override
+                public String getScope() {
+                    return scope;
+                }
+
+                @Override
+                public String getName() {
+                    return name;
+                }
+
+                @Override
+                public String getDescription() {
+                    Object property = reference.getProperty("osgi.command.description");
+                    if (property != null) {
+                        return property.toString();
+                    } else {
+                        return getName();
+                    }
+                }
+
+                @Override
+                public Completer getCompleter(final boolean scoped) {
+                    return null;
+                }
+
+                @Override
+                public Parser getParser() {
+                    return null;
+                }
+
+                @Override
+                public Object execute(Session session, List<Object> arguments) throws Exception {
+                    // TODO: remove not really nice cast
+                    CommandSession commandSession = (CommandSession) session.get(".commandSession");
+                    return target.execute(commandSession, arguments);
+                }
+            };
+            sessionFactory.getRegistry().register(command);
+            commands.add(command);
+        }
+        return commands;
+    }
+
+    @Override
+    public void removedService(ServiceReference<Object> reference, List<Command> commands) {
+        for (Command command : commands) {
+            sessionFactory.getRegistry().unregister(command);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/EventAdminListener.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/EventAdminListener.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/EventAdminListener.java
index 73c741e..820cace 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/EventAdminListener.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/EventAdminListener.java
@@ -22,8 +22,8 @@ import java.io.Closeable;
 import java.util.HashMap;
 import java.util.Map;
 
-import org.apache.felix.gogo.api.CommandSessionListener;
 import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.CommandSessionListener;
 import org.osgi.framework.BundleContext;
 import org.osgi.service.event.Event;
 import org.osgi.service.event.EventAdmin;

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LoggingCommandSessionListener.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LoggingCommandSessionListener.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LoggingCommandSessionListener.java
index 536ed17..47386a8 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LoggingCommandSessionListener.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LoggingCommandSessionListener.java
@@ -21,8 +21,8 @@ package org.apache.karaf.shell.impl.console.osgi;
 import java.util.Collection;
 import java.util.Collections;
 
-import org.apache.felix.gogo.api.CommandSessionListener;
 import org.apache.felix.service.command.CommandSession;
+import org.apache.felix.service.command.CommandSessionListener;
 import org.apache.karaf.shell.api.console.CommandLoggingFilter;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java
index 822c712..67ecdb7 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredCommand.java
@@ -76,16 +76,32 @@ public class SecuredCommand implements Command, Function {
             Object v = arguments.get(i);
             if (v instanceof Closure) {
                 final Closure closure = (Closure) v;
-                arguments.set(i, new org.apache.karaf.shell.api.console.Function() {
-                    @Override
-                    public Object execute(Session session, List<Object> arguments) throws Exception {
-                        return closure.execute(commandSession, arguments);
-                    }
-                });
+                arguments.set(i, new VersatileFunction(closure));
             }
         }
         return execute(session, arguments);
     }
 
+    static class VersatileFunction implements org.apache.felix.service.command.Function,
+            org.apache.karaf.shell.api.console.Function {
+
+        private final Closure closure;
+
+        VersatileFunction(Closure closure) {
+            this.closure = closure;
+        }
+
+
+        @Override
+        public Object execute(CommandSession commandSession, List<Object> list) throws Exception {
+            return closure.execute(commandSession, list);
+        }
+
+        @Override
+        public Object execute(Session session, List<Object> arguments) throws Exception {
+            CommandSession commandSession = (CommandSession) session.get(".commandSession");
+            return closure.execute(commandSession, arguments);
+        }
+    }
 
 }


[3/3] karaf git commit: [KARAF-397] Allow completion of non Karaf based osgi commands [KARAF-2454] Portable way to make custom shell commands

Posted by gn...@apache.org.
[KARAF-397] Allow completion of non Karaf based osgi commands
[KARAF-2454] Portable way to make custom shell commands

Leverage more of the gogo-jline bundle, such as builtin commands, completion mechanism.
Remove duplicate commands from Karaf (which has the benefit of making sure all builtin commands are available when the session is created, so when the initialization script runs).

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

Branch: refs/heads/master
Commit: f1dd4a94c8d3cd05ca35513256e9e787dffc42c9
Parents: 42ef364
Author: Guillaume Nodet <gn...@apache.org>
Authored: Wed Oct 12 11:14:43 2016 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Wed Oct 19 11:05:32 2016 +0200

----------------------------------------------------------------------
 .../etc/org.apache.karaf.command.acl.shell.cfg  |   2 +-
 .../etc/scripts/shell.completion.script         | 238 +++++++++++
 .../resources/resources/etc/shell.init.script   |  19 +
 .../resources/resources/etc/system.properties   |   8 +-
 .../karaf/itests/ShellCommandSecurityTest.java  |   6 +-
 pom.xml                                         |   6 +-
 .../karaf/shell/commands/impl/AliasAction.java  |  42 --
 .../karaf/shell/commands/impl/CatAction.java    | 125 ------
 .../karaf/shell/commands/impl/ClearAction.java  |  39 --
 .../karaf/shell/commands/impl/DateAction.java   | 132 ------
 .../karaf/shell/commands/impl/EachAction.java   |  53 ---
 .../karaf/shell/commands/impl/EchoAction.java   |  57 ---
 .../karaf/shell/commands/impl/EditAction.java   |  55 ---
 .../karaf/shell/commands/impl/EnvAction.java    |  52 ---
 .../karaf/shell/commands/impl/GrepAction.java   | 260 ------------
 .../karaf/shell/commands/impl/HeadAction.java   | 108 -----
 .../shell/commands/impl/HistoryAction.java      |  56 ---
 .../karaf/shell/commands/impl/IfAction.java     |  75 ----
 .../karaf/shell/commands/impl/LessAction.java   | 104 -----
 .../karaf/shell/commands/impl/MoreAction.java   | 144 -------
 .../karaf/shell/commands/impl/NewAction.java    | 379 -----------------
 .../karaf/shell/commands/impl/SleepAction.java  |  58 ---
 .../karaf/shell/commands/impl/SortAction.java   | 404 -------------------
 .../karaf/shell/commands/impl/TacAction.java    |  77 ----
 .../karaf/shell/commands/impl/TailAction.java   | 136 -------
 .../karaf/shell/commands/impl/WcAction.java     | 218 ----------
 .../karaf/shell/commands/impl/WhileAction.java  |  73 ----
 .../services/org/apache/karaf/shell/commands    |  19 -
 .../apache/karaf/shell/commands/impl/grep.txt   |   1 -
 .../org/apache/karaf/shell/commands/impl/wc.txt |  35 --
 .../karaf/shell/commands/impl/GrepTest.java     | 312 --------------
 .../karaf/shell/commands/impl/SortTest.java     |  91 -----
 shell/console/pom.xml                           |   7 +-
 .../karaf/shell/compat/CommandTracker.java      | 101 +----
 .../impl/SecuredCommandProcessorImpl.java       |   9 +-
 shell/core/pom.xml                              |   3 +-
 .../shell/impl/console/CommandWrapper.java      |   7 +-
 .../shell/impl/console/ConsoleSessionImpl.java  | 118 ++++--
 .../shell/impl/console/HistoryWrapper.java      |   2 +-
 .../shell/impl/console/SessionFactoryImpl.java  | 100 ++---
 .../shell/impl/console/osgi/Activator.java      |   6 +
 .../shell/impl/console/osgi/CommandTracker.java | 118 ++++++
 .../impl/console/osgi/EventAdminListener.java   |   2 +-
 .../osgi/LoggingCommandSessionListener.java     |   2 +-
 .../console/osgi/secured/SecuredCommand.java    |  28 +-
 45 files changed, 560 insertions(+), 3327 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/assemblies/features/base/src/main/resources/resources/etc/org.apache.karaf.command.acl.shell.cfg
----------------------------------------------------------------------
diff --git a/assemblies/features/base/src/main/resources/resources/etc/org.apache.karaf.command.acl.shell.cfg b/assemblies/features/base/src/main/resources/resources/etc/org.apache.karaf.command.acl.shell.cfg
index 28880b6..2afc19b 100644
--- a/assemblies/features/base/src/main/resources/resources/etc/org.apache.karaf.command.acl.shell.cfg
+++ b/assemblies/features/base/src/main/resources/resources/etc/org.apache.karaf.command.acl.shell.cfg
@@ -23,7 +23,7 @@
 # For an explanation of the syntax of this file, see the file:
 #   org.apache.karaf.command.acl.system.cfg
 #
-edit = admin
+nano = admin
 exec = admin
 new = admin
 java = admin

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/assemblies/features/base/src/main/resources/resources/etc/scripts/shell.completion.script
----------------------------------------------------------------------
diff --git a/assemblies/features/base/src/main/resources/resources/etc/scripts/shell.completion.script b/assemblies/features/base/src/main/resources/resources/etc/scripts/shell.completion.script
new file mode 100644
index 0000000..e8595e5
--- /dev/null
+++ b/assemblies/features/base/src/main/resources/resources/etc/scripts/shell.completion.script
@@ -0,0 +1,238 @@
+//
+// 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.
+//
+// This script is run each time a shell is created.
+// You can define here closures or variables that will be available
+// in each session.
+//
+
+__option_not_present = {
+  res = true
+  opts = $argv
+  each $opts {
+      arg = $it
+      each ($.commandLine words) {
+          if { ($it toString) equals ($arg toString) } {
+              res = false
+          }
+      }
+  }
+  $res
+}
+
+__set_unset_arguments = {
+  is_setopt = (($.commandLine words) get 0) equals "setopt"
+  enums = ((__load_class 'org.jline.reader.LineReader$Option') enumConstants)
+  candidates = new ArrayList
+  each $enums {
+      name = ${(GL)it/_/-}
+      is_set = ($.reader isSet $it)
+      neg = %(( if(is_setopt, is_set, not(is_set)) ))
+      if { $neg } {
+          name = "no-${name}"
+      }
+      if { not  { (($.commandLine words) subList 1 ($.commandLine wordIndex)) contains $name } } {
+          $candidates add (new org.jline.reader.Candidate $name $name (if { $neg } { "unset" } { "set" }) null null null true)
+      }
+  }
+  $candidates
+}
+
+
+complete -c shell:complete -e
+complete -c shell:complete -d "Edit command specific completions"
+complete -c shell:complete -s c -l command --description "Command to add completion to" -n '__option_not_present -c --command' -a '$.commands'
+complete -c shell:complete -s s -l short-option --description "Posix-style option to complete" -n '__option_not_present -s --short-option'
+complete -c shell:complete -s l -l long-option --description "GNU-style option to complete" -n '__option_not_present -l --long-option'
+complete -c shell:complete -s a -l arguments --description "A list of possible arguments" -n '__option_not_present -a --argument'
+complete -c shell:complete -s d -l description --description "Description of this completions" -n '__option_not_present -d --description'
+complete -c shell:complete -s h -l help --description "Display help and exit" -n '__option_not_present -h --help'
+complete -c shell:complete -s n -l condition --description "The completion should only be used if the specified command has a zero exit status"  -n '__option_not_present -n --condition'
+complete -c shell:complete -s e -l erase --description "Remove completion"  -n '__option_not_present -e --erase'
+
+complete -c shell:history -e
+complete -c shell:history -d "Show and manipulate command history"
+complete -c shell:history -l clear --description "Clear history" -n '__option_not_present --clear'
+complete -c shell:history -l save --description "Save history" -n '__option_not_present --save'
+
+complete -c shell:setopt -e
+complete -c shell:setopt -d "Set or view set shell options"
+complete -c shell:setopt -a '__set_unset_arguments'
+
+complete -c shell:unsetopt -e
+complete -c shell:unsetopt -d "Unset or view unset shell options"
+complete -c shell:unsetopt -a '__set_unset_arguments'
+
+complete -c shell:cat -e
+complete -c shell:cat -d "Concatenate and print files"
+complete -c shell:cat -s n "Number the output lines, starting at 1"
+complete -c shell:cat -a '__files'
+
+complete -c shell:pwd -e
+complete -c shell:pwd -d "Get current directory"
+
+complete -c shell:ls -e
+complete -c shell:ls -d "List files"
+
+complete -c shell:cd -e
+complete -c shell:cd -d "Change current directory"
+complete -c shell:cd -a '__directories'
+
+complete -c shell:sleep -e
+complete -c shell:sleep -d "Pause execution for the specified amount of time"
+
+complete -c shell:echo -e
+complete -c shell:echo -d "Write arguments to the standard output"
+complete -c shell:echo -s n -d "No trailing new line"
+
+complete -c shell:grep -e
+complete -c shell:grep -d "File pattern searcher"
+# TODO
+
+complete -c shell:sort -e
+complete -c shell:sort -d "Sort lines of text files"
+# TODO
+
+complete -c shell:gosh -e
+complete -c shell:gosh -d "Execute script with arguments in a new session"
+# TODO
+
+complete -c shell:sh -e
+complete -c shell:sh -d "Execute script with arguments in a new session"
+# TODO
+
+complete -c shell:source -e
+complete -c shell:source -d "Execute script with arguments"
+# TODO
+
+# TODO: format getopt new set tac type addcommand removeCommand eval
+
+complete -c shell:break -e
+complete -c shell:break -d "Break from a loop"
+
+complete -c shell:continue -e
+complete -c shell:continue -d "Continue to next iteration in a loop"
+
+complete -c shell:each -e
+complete -c shell:each -d "Loop and execute script on the specified elements"
+
+complete -c shell:if -e
+complete -c shell:if -d "Conditionaly execute a script"
+
+complete -c shell:new -e
+complete -c shell:new -d "Creates new instance of the given java class"
+
+complete -c shell:not -e
+complete -c shell:not -d "Negates the result of a script"
+
+complete -c shell:throw -e
+complete -c shell:throw -d "Throws an exception"
+
+complete -c shell:try -e
+complete -c shell:try -d "Try executing a script and catch any exception"
+
+complete -c shell:until -e
+complete -c shell:until -d "Loop and execute script until a condition is satisfied"
+
+complete -c shell:while -e
+complete -c shell:while -d "Loop and execute script while a condition is satisfied"
+
+complete -c shell:less -e
+complete -c shell:less -d "File pager"
+complete -c shell:less -s e -l quit-at-eof --description "Exit on second EOF"
+complete -c shell:less -s E -l QUIT-AT-EOF --description "Exit on EOF"
+complete -c shell:less -s q -l quiet -l silent --description "Silent mode"
+complete -c shell:less -s Q -l QUIET -l SILENT --description "Completely  silent"
+complete -c shell:less -s S -l chop-long-lines --description "Do not fold long lines"
+complete -c shell:less -s i -l ignore-case --description "Search ignores lowercase case"
+complete -c shell:less -s I -l IGNORE-CASE --description "Search ignores all case"
+complete -c shell:less -s x -l tabs --description "Set tab stops"
+complete -c shell:less -s N -l LINE-NUMBERS --description "Display line number for each line"
+complete -c shell:less -a '__files'
+
+complete -c shell:nano -e
+complete -c shell:nano -d "File editor"
+complete -c shell:nano -a '__files'
+
+complete -c shell:keymap -e
+complete -c shell:keymap -d "Manipulate keymaps"
+complete -c shell:keymap -s N --description "Create a new keymap" -n '__option_not_present -N -d -D -l -r -s -A'
+complete -c shell:keymap -s d --description "Delete existing keymaps and reset to default state" -n '__option_not_present -N -d -D -l -r -s -A'
+complete -c shell:keymap -s D --description "Delete named keymaps" -n '__option_not_present -N -d -D -l -r -s -A'
+complete -c shell:keymap -s l --description "List existing keymap names" -n '__option_not_present -N -d -D -l -r -s -A'
+complete -c shell:keymap -s r --description "Unbind specified in-strings" -n '__option_not_present -N -d -D -l -r -s -A'
+complete -c shell:keymap -s s --description "Bind each in-string to each out-string" -n '__option_not_present -N -d -D -l -r -s -A'
+complete -c shell:keymap -s A --description "Create alias to keymap" -n '__option_not_present -N -d -D -l -r -s -A'
+complete -c shell:keymap -s e --description "Select emacs keymap and bind it to main" -n '__option_not_present -e -a -v -M'
+complete -c shell:keymap -s v --description "Select viins keymap and bind it to main" -n '__option_not_present -e -a -v -M'
+complete -c shell:keymap -s a --description "Select vicmd keymap" -n '__option_not_present -e -a -v -M'
+complete -c shell:keymap -s M --description "Specify keymap to select" -n '__option_not_present -e -a -v -M' -a '(keymap -l | tac) split " "'
+complete -c shell:keymap -s R --description "Interpret in-strings as ranges"
+complete -c shell:keymap -s p --description "List bindings which have given key sequence as a a prefix"
+complete -c shell:keymap -s L --description "Output in form of keymap commands"
+
+complete -c shell:widget -e
+complete -c shell:widget -d "Manipulate widgets"
+complete -c shell:widget -s N --description "Create a new widget" -n '__option_not_present -N -A -D -U -l'
+complete -c shell:widget -s A --description "Create alias to widget" -n '__option_not_present -N -A -D -U -l'
+complete -c shell:widget -s D --description "Delete widgets" -n '__option_not_present -N -A -D -U -l'
+complete -c shell:widget -s U --description "Push characters to the stack" -n '__option_not_present -N -A -D -U -l'
+complete -c shell:widget -s l --description "List user-defined widgets" -n '__option_not_present -N -A -D -U -l'
+complete -c shell:widget -s a --description "With -l, list all widgets" -n '__option_not_present -l'
+
+complete -c shell:bg -e
+complete -c shell:bg -d "Put job in background"
+
+complete -c shell:fg -e
+complete -c shell:fg -d "Put job in foreground"
+
+complete -c shell:jobs -e
+complete -c shell:jobs -d "List jobs"
+
+complete -c shell:clear -e
+complete -c shell:clear -d "Clear screen"
+
+complete -c shell:head -e
+complete -c shell:head -d "Displays first lines of file"
+complete -c shell:head -s n -l lines --description "Print line counts"
+complete -c shell:head -s c -l bytes --description "Print byte counts"
+complete -c shell:head -a '__files'
+
+complete -c shell:tail -e
+complete -c shell:tail -d "Displays last lines of file"
+complete -c shell:tail -s q -l quiet --description "Suppress headers when printing multiple sources"
+complete -c shell:tail -s f -l follow --description "Do not stop at end of file"
+complete -c shell:tail -s F -l FOLLOW --description "Follow and check for file renaming or rotation"
+complete -c shell:tail -s n -l lines --description "Number of lines to print"
+complete -c shell:tail -s c -l bytes --description "Number of bytes to print"
+complete -c shell:tail -a '__files'
+
+complete -c shell:date -e
+complete -c shell:date -d "Display date and time"
+complete -c shell:date -s u --description "Use UTC"
+complete -c shell:date -s r --description "Print the date represented by 'seconds' since January 1, 1970"
+complete -c shell:date -s v --description "Adjust date"
+complete -c shell:date -s f --description "Use 'input_fmt' to parse 'new_date'"
+
+complete -c shell:wc -e
+complete -c shell:wc -d "Word, line, character, and byte count"
+complete -c shell:wc -s n -l lines --description "Print line count"
+complete -c shell:wc -s c -l bytes --description "Print byte count"
+complete -c shell:wc -s m -l chars --description "Print character count"
+complete -c shell:wc -s w -l words --description "Print word count"
+complete -c shell:wc -a '__files'

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/assemblies/features/base/src/main/resources/resources/etc/shell.init.script
----------------------------------------------------------------------
diff --git a/assemblies/features/base/src/main/resources/resources/etc/shell.init.script b/assemblies/features/base/src/main/resources/resources/etc/shell.init.script
index 5977a44..382c759 100644
--- a/assemblies/features/base/src/main/resources/resources/etc/shell.init.script
+++ b/assemblies/features/base/src/main/resources/resources/etc/shell.init.script
@@ -30,3 +30,22 @@ help = { *:help $args | more } ;
 man = { help $args } ;
 log:list = { log:get ALL } ;
 service:get = { $.context getService ($.context getServiceReference $args) };
+
+env = { shell:set $args }
+edit = { shell:nano $args }
+more = { shell:less $args }
+
+prompt = "${USER}@${APPLICATION}(${SUBSHELL})> "
+
+__load_class = {
+  (($.reader class) classLoader) loadClass $1
+}
+__rprompt_formatter = (((__load_class java.text.SimpleDateFormat) getConstructor (__load_class java.lang.String)) newInstance \'$'\u001B\[90m'\'HH:mm:ss)
+__date_class = (__load_class java.util.Date)
+\#rprompt = { $__rprompt_formatter format ($__date_class newInstance) }
+
+setopt group
+keymap "^[OA" up-line-or-search
+keymap "^[OB" down-line-or-search
+
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/assemblies/features/base/src/main/resources/resources/etc/system.properties
----------------------------------------------------------------------
diff --git a/assemblies/features/base/src/main/resources/resources/etc/system.properties b/assemblies/features/base/src/main/resources/resources/etc/system.properties
index 264dbea..6c4525c 100644
--- a/assemblies/features/base/src/main/resources/resources/etc/system.properties
+++ b/assemblies/features/base/src/main/resources/resources/etc/system.properties
@@ -47,7 +47,7 @@ karaf.default.repository = system
 # session.  This script can be used to create aliases and define
 # additional commands.
 #
-karaf.shell.init.script = ${karaf.etc}/shell.init.script
+karaf.shell.init.script = ${karaf.etc}/shell.init.script,${karaf.etc}/scripts/*.script
 
 #
 # Sets the maximum size of the shell command history. If not set,
@@ -88,12 +88,6 @@ karaf.local.roles = admin,manager,viewer,systembundles
 xml.catalog.files =
 
 #
-# Suppress the bell in the console when hitting backspace too many times
-# for example
-#
-jline.nobell = true
-
-#
 # ServiceMix specs options
 #
 org.apache.servicemix.specs.debug = false

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/itests/src/test/java/org/apache/karaf/itests/ShellCommandSecurityTest.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/karaf/itests/ShellCommandSecurityTest.java b/itests/src/test/java/org/apache/karaf/itests/ShellCommandSecurityTest.java
index a5e9ce1..0aed5d3 100644
--- a/itests/src/test/java/org/apache/karaf/itests/ShellCommandSecurityTest.java
+++ b/itests/src/test/java/org/apache/karaf/itests/ShellCommandSecurityTest.java
@@ -19,6 +19,8 @@ import org.ops4j.pax.exam.junit.PaxExam;
 import org.ops4j.pax.exam.spi.reactors.ExamReactorStrategy;
 import org.ops4j.pax.exam.spi.reactors.PerClass;
 
+import static org.jline.keymap.KeyMap.ctrl;
+
 /**
  * This test exercises the Shell Command ACL for the shell scope commands as defined in
  * /framework/src/main/resources/resources/etc/org.apache.karaf.command.acl.shell.cfg
@@ -35,13 +37,13 @@ public class ShellCommandSecurityTest extends SshCommandTestBase {
         addViewer(vieweruser);
 
         assertCommand(vieweruser, "shell:date", Result.OK);
-        assertCommand(vieweruser, "shell:edit", Result.NOT_FOUND);
+        assertCommand(vieweruser, "shell:nano", Result.NOT_FOUND);
         assertCommand(vieweruser, "shell:exec", Result.NOT_FOUND);
         assertCommand(vieweruser, "shell:new", Result.NOT_FOUND);
         assertCommand(vieweruser, "shell:java", Result.NOT_FOUND);
 
         assertCommand("karaf", "shell:date", Result.OK);
-        assertCommand("karaf", "shell:edit", Result.OK);
+        assertCommand("karaf", "shell:nano\n" + ctrl('X'), Result.OK);
         assertCommand("karaf", "shell:exec", Result.OK);
         assertCommand("karaf", "shell:new", Result.OK);
         assertCommand("karaf", "shell:java", Result.OK);

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index b03ae9d..a3e2758 100644
--- a/pom.xml
+++ b/pom.xml
@@ -187,8 +187,8 @@
         <felix.fileinstall.version>3.5.6</felix.fileinstall.version>
         <felix.framework.version>5.6.0</felix.framework.version>
         <felix.framework.security.version>2.4.0</felix.framework.security.version>
-        <felix.gogo.runtime.version>0.17.0-SNAPSHOT</felix.gogo.runtime.version>
-        <felix.gogo.jline.version>0.1.0-SNAPSHOT</felix.gogo.jline.version>
+        <felix.gogo.runtime.version>1.0.0</felix.gogo.runtime.version>
+        <felix.gogo.jline.version>1.0.0</felix.gogo.jline.version>
         <felix.inventory.version>1.0.4</felix.inventory.version>
         <felix.plugin.version>3.0.1</felix.plugin.version>
         <felix.utils.version>1.8.2</felix.utils.version>
@@ -252,7 +252,7 @@
         <hibernate.validator.version>5.3.0.Final</hibernate.validator.version>
         <jansi.version>1.14</jansi.version>
         <javassist.version>3.9.0.GA</javassist.version>
-        <jline.version>3.0.0.M2</jline.version>
+        <jline.version>3.0.0</jline.version>
         <jsw.version>3.2.3</jsw.version>
         <log4j.version>1.2.17</log4j.version>
         <maven.version>2.0.9</maven.version>

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/AliasAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/AliasAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/AliasAction.java
deleted file mode 100644
index 21db405..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/AliasAction.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "shell", name = "alias", description = "Create an alias to a command")
-@Service
-public class AliasAction implements Action {
-
-    @Argument(index = 0, name = "command", description = "The command to alias, e.g. 'ldn = { log:display -n $args }'", required = true, multiValued = false)
-    private String alias;
-
-    @Reference
-    private Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        session.execute(alias);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/CatAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/CatAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/CatAction.java
deleted file mode 100644
index 0471c56..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/CatAction.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.File;
-import java.io.InputStreamReader;
-import java.io.Reader;
-import java.net.URL;
-import java.net.MalformedURLException;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.completers.FileOrUriCompleter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Concatenate and print files and/or URLs.
- */
-@Command(scope = "shell", name = "cat", description = "Displays the content of a file or URL.")
-@Service
-public class CatAction implements Action {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    @Option(name = "-n", aliases = {}, description = "Number the output lines, starting at 1.", required = false, multiValued = false)
-    private boolean displayLineNumbers;
-
-    @Option(name = "-", description = "Use stdin")
-    private boolean stdin;
-
-    @Argument(index = 0, name = "paths or urls", description = "A list of file paths or urls to display separated by whitespace (use - for STDIN)", required = false, multiValued = true)
-    @Completion(FileOrUriCompleter.class)
-    private List<String> paths;
-
-    @Override
-    public Object execute() throws Exception {
-        if (stdin) {
-            paths = Collections.singletonList("-");
-        }
-
-        if (paths == null) {
-            throw new RuntimeException("Need to supply a path");
-        }
-
-        for (String filename : paths) {
-            BufferedReader reader = new BufferedReader(createReader(filename));
-            try {
-                cat(reader);
-            } finally {
-                closeReader(reader);
-            }
-        }
-
-        return null;
-    }
-
-    private void closeReader(BufferedReader reader) {
-        try {
-            reader.close();
-        } catch (IOException e) {
-            // Ignore
-        }
-    }
-
-    /**
-     * Create a reader for a url orfor a file
-     * 
-     * @param urlOrfileName
-     * @return
-     * @throws IOException
-     * @throws FileNotFoundException
-     */
-    private Reader createReader(String urlOrfileName) throws IOException, FileNotFoundException {
-        if ("-".equals(urlOrfileName)) {
-            log.debug("Printing STDIN");
-            return new InputStreamReader(System.in);
-        }
-        try {
-            URL url = new URL(urlOrfileName);
-            log.debug("Printing URL: " + url);
-            return new InputStreamReader(url.openStream());
-        } catch (MalformedURLException ignore) {
-            File file = new File(urlOrfileName);
-            log.debug("Printing file: " + file);
-            return new FileReader(file);
-        }
-    }
-
-    private void cat(final BufferedReader reader) throws IOException {
-        String line;
-        int lineno = 1;
-
-        while ((line = reader.readLine()) != null) {
-            if (displayLineNumbers) {
-                System.out.print(String.format("%6d  ", lineno++));
-            }
-            System.out.println(line);
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/ClearAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/ClearAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/ClearAction.java
deleted file mode 100644
index 805ec25..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/ClearAction.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * A command to clear the console buffer
- */
-@Command(scope = "shell", name = "clear", description = "Clears the console buffer.")
-@Service
-public class ClearAction implements Action {
-
-    @Override
-    public Object execute() throws Exception {
-		System.out.print("\33[2J");
-		System.out.flush();
-		System.out.print("\33[1;1H");
-		System.out.flush();
-        return null;
-	}
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/DateAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/DateAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/DateAction.java
deleted file mode 100644
index 880ae43..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/DateAction.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-import java.text.DateFormat;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
-@Command(scope = "shell", name = "date", description = "Display the current time in the given FORMAT")
-@Service
-public class DateAction implements Action {
-
-    @Option(name = "-d", aliases = { "--date" }, description = "Display time described, not now", multiValued = false, required = false)
-    private String date;
-
-    @Argument(index = 0, name = "format", description = "Output format", multiValued = false, required = false)
-    private String format;
-
-    @Override
-    public Object execute() throws Exception {
-        Date d;
-        if (date == null || date.equalsIgnoreCase("now")) {
-            d = new Date();
-        } else {
-            if (date.startsWith("@")) {
-                d = new Date(Long.parseLong(date.substring(1)));
-            } else {
-                d = new Date(date);
-            }
-        }
-        if (format == null) {
-            format = "%+";
-        }
-        // transform Unix format to Java SimpleDateFormat (if required)
-        StringBuilder sb = new StringBuilder();
-        boolean quote = false;
-        for (int i = 0; i < format.length(); i++) {
-            char c = format.charAt(i);
-            if (c == '%') {
-                if (i + 1 < format.length()) {
-                    if (quote) {
-                        sb.append('\'');
-                        quote = false;
-                    }
-                    c = format.charAt(++i);
-                    switch (c) {
-                        case '+':
-                        case 'A': sb.append("MMM EEE d HH:mm:ss yyyy"); break;
-                        case 'a': sb.append("EEE"); break;
-                        case 'B': sb.append("MMMMMMM"); break;
-                        case 'b': sb.append("MMM"); break;
-                        case 'C': sb.append("yy"); break;
-                        case 'c': sb.append("MMM EEE d HH:mm:ss yyyy"); break;
-                        case 'D': sb.append("MM/dd/yy"); break;
-                        case 'd': sb.append("dd"); break;
-                        case 'e': sb.append("dd"); break;
-                        case 'F': sb.append("yyyy-MM-dd"); break;
-                        case 'G': sb.append("YYYY"); break;
-                        case 'g': sb.append("YY"); break;
-                        case 'H': sb.append("HH"); break;
-                        case 'h': sb.append("MMM"); break;
-                        case 'I': sb.append("hh"); break;
-                        case 'j': sb.append("DDD"); break;
-                        case 'k': sb.append("HH"); break;
-                        case 'l': sb.append("hh"); break;
-                        case 'M': sb.append("mm"); break;
-                        case 'm': sb.append("MM"); break;
-                        case 'N': sb.append("S"); break;
-                        case 'n': sb.append("\n"); break;
-                        case 'P': sb.append("aa"); break;
-                        case 'p': sb.append("aa"); break;
-                        case 'r': sb.append("hh:mm:ss aa"); break;
-                        case 'R': sb.append("HH:mm"); break;
-                        case 'S': sb.append("ss"); break;
-                        case 's': sb.append("S"); break;
-                        case 'T': sb.append("HH:mm:ss"); break;
-                        case 't': sb.append("\t"); break;
-                        case 'U': sb.append("w"); break;
-                        case 'u': sb.append("u"); break;
-                        case 'V': sb.append("W"); break;
-                        case 'v': sb.append("dd-MMM-yyyy"); break;
-                        case 'W': sb.append("w"); break;
-                        case 'w': sb.append("u"); break;
-                        case 'X': sb.append("HH:mm:ss"); break;
-                        case 'x': sb.append("MM/dd/yy"); break;
-                        case 'Y': sb.append("yyyy"); break;
-                        case 'y': sb.append("yy"); break;
-                        case 'Z': sb.append("z"); break;
-                        case 'z': sb.append("X"); break;
-                        case '%': sb.append("%"); break;
-                    }
-                } else {
-                    if (!quote) {
-                        sb.append('\'');
-                    }
-                    sb.append(c);
-                    sb.append('\'');
-                }
-            } else {
-                if ((c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') && !quote) {
-                    sb.append('\'');
-                    quote = true;
-                }
-                sb.append(c);
-            }
-        }
-        DateFormat df = new SimpleDateFormat(sb.toString());
-        System.out.println(df.format(d));
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EachAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EachAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EachAction.java
deleted file mode 100644
index 0de344e..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EachAction.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Function;
-import org.apache.karaf.shell.api.console.Session;
-
-/**
- * Execute a closure on a list of arguments.
- */
-@Command(scope = "shell", name = "each", description = "Execute a closure on a list of arguments.")
-@Service
-public class EachAction implements Action {
-
-    @Argument(name = "values", index = 0, multiValued = false, required = true, description = "The collection of arguments to iterate on")
-    Collection<Object> values;
-
-    @Argument(name = "function", index = 1, multiValued = false, required = true, description = "The function to execute")
-    Function function;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        for (Object v : values) {
-            function.execute(session, Collections.singletonList(v));
-        }
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EchoAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EchoAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EchoAction.java
deleted file mode 100644
index 433e2a9..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EchoAction.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-@Command(scope = "shell", name = "echo", description="Echoes or prints arguments to STDOUT.")
-@Service
-public class EchoAction implements Action
-{
-    @Option(name = "-n", aliases = {}, description = "Do not print the trailing newline character", required = false, multiValued = false)
-    private boolean noTrailingNewline = false;
-
-    @Argument(index = 0, name = "arguments", description="Arguments to display separated by whitespaces", required = false, multiValued = true)
-    private List<String> args;
-
-    @Override
-    public Object execute() throws Exception {
-        if (args != null) {
-            boolean first = true;
-            for (String arg : args) {
-                if (first) {
-                    first = false;
-                } else {
-                    System.out.print(" ");
-                }
-                System.out.print(arg);
-            }
-        }
-
-        if (!noTrailingNewline) {
-            System.out.println();
-        }
-
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java
deleted file mode 100644
index 84feb70..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EditAction.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.api.console.Terminal;
-
-@Command(scope = "shell", name = "edit", description = "Calls a text editor.")
-@Service
-public class EditAction implements Action {
-
-    private final Pattern URL_PATTERN = Pattern.compile("[^: ]+:[^ ]+");
-
-    @Argument(index = 0, name = "url", description = "The url of the resource to edit.", required = true, multiValued = true)
-    private List<String> urls;
-
-    @Reference
-    Session session;
-
-    @Reference
-    Terminal terminal;
-
-    @Override
-    public Object execute() throws Exception {
-        org.jline.terminal.Terminal terminal = (org.jline.terminal.Terminal) session.get(".jline.terminal");
-        Path pwd = Paths.get(System.getProperty("karaf.home"));
-        org.jline.builtins.Commands.nano(terminal, System.out, System.err, pwd,
-                urls.toArray(new String[urls.size()]));
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EnvAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EnvAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EnvAction.java
deleted file mode 100644
index 2bd0755..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/EnvAction.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-
-/**
- * Command to get/set the value of a session variable.
- */
-@Command(scope = "shell", name = "env", description = "Get/set the value of a console session variable.")
-@Service
-public class EnvAction implements Action {
-
-    @Argument(index = 0, name = "variable", description = "The name of the console session variable.", required = true, multiValued = false)
-    String variable;
-
-    @Argument(index = 1, name = "value", description = "The new value of the console session variable.", required = false, multiValued = false)
-    String value;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        if (value == null) {
-            System.out.println(session.get(variable));
-        } else {
-            session.put(variable, value);
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java
deleted file mode 100644
index 6dcb054..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/GrepAction.java
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.felix.gogo.api.Process;
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Completion;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.FileOrUriCompleter;
-import org.jline.builtins.Source;
-import org.jline.builtins.Source.StdInSource;
-import org.jline.builtins.Source.URLSource;
-import org.jline.terminal.Terminal;
-import org.jline.utils.AttributedString;
-import org.jline.utils.AttributedStringBuilder;
-import org.jline.utils.AttributedStyle;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-@Command(scope = "shell", name="grep", description="Prints lines matching the given pattern.", detailedDescription="classpath:grep.txt")
-@Service
-public class GrepAction implements Action {
-
-    public static enum ColorOption {
-        never,
-        always,
-        auto
-    }
-
-    @Argument(index = 0, name = "pattern", description = "Regular expression", required = true, multiValued = false)
-    private String regex;
-
-    @Argument(index = 1, multiValued = true)
-    @Completion(FileOrUriCompleter.class)
-    List<String> files;
-
-    @Option(name = "-n", aliases = { "--line-number" }, description = "Prefixes each line of output with the line number within its input file.", required = false, multiValued = false)
-    private boolean lineNumber;
-
-    @Option(name = "-v", aliases = { "--invert-match" }, description = "Inverts the sense of matching, to select non-matching lines.", required = false, multiValued = false)
-    private boolean invertMatch;
-
-    @Option(name = "-w", aliases = { "--word-regexp" }, description = "Selects only those lines containing matches that form whole " +
-                                                                      "words.  The test is that the matching substring must either be " +
-                                                                      "at  the beginning of the line, or preceded by a non-word constituent " +
-                                                                      "character.  Similarly, it must be either at the end of " +
-                                                                      "the line or followed by a non-word constituent character.  " +
-                                                                      "Word-constituent characters are letters, digits, and the underscore.", required = false, multiValued = false)
-    private boolean wordRegexp;
-
-    @Option(name = "-x", aliases = { "--line-regexp" }, description = "Selects only those matches that exactly match the whole line.", required = false, multiValued = false)
-    private boolean lineRegexp;
-
-    @Option(name = "-i", aliases = { "--ignore-case" }, description = "Ignores case distinctions in both the PATTERN and the input files.", required = false, multiValued = false)
-    private boolean ignoreCase;
-
-    @Option(name = "-c", aliases = { "--count" }, description = "only print a count of matching lines per FILE", required = false, multiValued = false)
-    private boolean count;
-
-    @Option(name = "--color", aliases = { "--colour" }, description = "use markers to distinguish the matching string. WHEN may be `always', `never' or `auto'", required = false, multiValued = false)
-    private ColorOption color = ColorOption.auto;
-
-    @Option(name = "-B", aliases = { "--before-context" }, description = "Print NUM lines of leading context before matching lines.  Places a line containing -- between contiguous groups of matches.", required = false, multiValued = false)
-    private int before = -1;
-
-    @Option(name = "-A", aliases = { "--after-context" }, description = "Print NUM lines of trailing context after matching lines.  Places a line containing -- between contiguous groups of matches.", required = false, multiValued = false)
-    private int after = -1;
-
-    @Option(name = "-C", aliases = { "--context" }, description = "Print NUM lines of output context.  Places a line containing -- between contiguous groups of matches.", required = false, multiValued = false)
-    private int context = 0;
-
-    @Option(name = "-o", aliases = { "--only-matching"}, description = "Print only the matching section of a line", required = false, multiValued = false)
-    private boolean onlyMatching;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        if (color == ColorOption.auto && (Process.current() == null || !Process.current().isTty(1))) {
-            color = ColorOption.never;
-        }
-        if (after < 0) {
-            after = context;
-        }
-        if (before < 0) {
-            before = context;
-        }
-
-        String regexp = regex;
-        if (wordRegexp) {
-            regex = regexp = "\\b" + regexp + "\\b";
-        }
-        if (lineRegexp) {
-            regexp = "^" + regexp + "$";
-        } else {
-            regexp = ".*" + regexp + ".*";
-        }
-        Pattern p;
-        Pattern p2;
-        if (ignoreCase) {
-            p = Pattern.compile(regexp, Pattern.CASE_INSENSITIVE);
-            p2 = Pattern.compile(regex, Pattern.CASE_INSENSITIVE);
-        } else {
-            p = Pattern.compile(regexp);
-            p2 = Pattern.compile(regex);
-        }
-
-        List<Source> sources = new ArrayList<>();
-        if (files == null || files.isEmpty()) {
-            files = Collections.singletonList("-");
-        }
-        Path pwd = Paths.get(System.getProperty("karaf.home", System.getProperty("user.dir")));
-        for (String arg : files) {
-            if ("-".equals(arg)) {
-                sources.add(new StdInSource());
-            } else {
-                sources.add(new URLSource(pwd.toUri().resolve(arg).toURL(), arg));
-            }
-        }
-
-        Terminal terminal = session != null ? (Terminal) session.get(".jline.terminal") : null;
-        List<Object> output = new ArrayList<>();
-        for (Source source : sources) {
-            boolean firstPrint = true;
-            int nb = 0;
-            int lineno = 1;
-            String line;
-            int lineMatch = 0;
-            List<String> lines = new ArrayList<>();
-            try (BufferedReader r = new BufferedReader(new InputStreamReader(source.read()))) {
-                while ((line = r.readLine()) != null) {
-                    if (line.length() == 1 && line.charAt(0) == '\n') {
-                        break;
-                    }
-                    if (p.matcher(line).matches() ^ invertMatch) {
-                        AttributedStringBuilder sbl = new AttributedStringBuilder();
-                        if (color != ColorOption.never) {
-                            sbl.style(getSourceStyle());
-                        }
-                        if (!count && sources.size() > 1) {
-                            sbl.append(source.getName());
-                            sbl.append(":");
-                        }
-                        if (!count && lineNumber) {
-                            sbl.append(String.format("%6d  ", lineno));
-                        }
-                        sbl.style(AttributedStyle.DEFAULT);
-                        AttributedString aLine = AttributedString.fromAnsi(line);
-                        AttributedStyle style;
-                        Matcher matcher2 = p2.matcher(aLine.toString());
-                        if (!invertMatch && color != ColorOption.never) {
-                            style = getMatchingStyle();
-                        } else {
-                            style = AttributedStyle.DEFAULT;
-                        }
-                        if (invertMatch) {
-                            nb++;
-                            sbl.append(aLine);
-                        } else if (onlyMatching) {
-                            while (matcher2.find()) {
-                                int index = matcher2.start(0);
-                                int cur = matcher2.end();
-                                sbl.append(aLine.subSequence(index, cur), style);
-                                nb++;
-                            }
-                        } else {
-                            int cur = 0;
-                            while (matcher2.find()) {
-                                int index = matcher2.start(0);
-                                AttributedString prefix = aLine.subSequence(cur, index);
-                                sbl.append(prefix);
-                                cur = matcher2.end();
-                                sbl.append(aLine.subSequence(index, cur), style);
-                                nb++;
-                            }
-                            sbl.append(aLine.subSequence(cur, aLine.length()));
-                        }
-                        lines.add(sbl.toAnsi(terminal));
-                        lineMatch = lines.size();
-                    } else {
-                        if (lineMatch != 0 & lineMatch + after + before <= lines.size()) {
-                            if (!count) {
-                                if (!firstPrint && before + after > 0) {
-                                    output.add("--");
-                                } else {
-                                    firstPrint = false;
-                                }
-                                for (int i = 0; i < lineMatch + after; i++) {
-                                    output.add(lines.get(i));
-                                }
-                            }
-                            while (lines.size() > before) {
-                                lines.remove(0);
-                            }
-                            lineMatch = 0;
-                        }
-                        lines.add(line);
-                        while (lineMatch == 0 && lines.size() > before) {
-                            lines.remove(0);
-                        }
-                    }
-                    lineno++;
-                }
-                if (!count && lineMatch > 0) {
-                    if (!firstPrint && before + after > 0) {
-                        output.add("--");
-                    } else {
-                        firstPrint = false;
-                    }
-                    for (int i = 0; i < lineMatch + after && i < lines.size(); i++) {
-                        output.add(lines.get(i));
-                    }
-                }
-                if (count) {
-                    output.add(nb);
-                }
-            }
-        }
-        return output;
-    }
-
-    private AttributedStyle getSourceStyle() {
-        return AttributedStyle.DEFAULT.foreground(AttributedStyle.BLACK + AttributedStyle.BRIGHT);
-    }
-
-    private AttributedStyle getMatchingStyle() {
-        return AttributedStyle.DEFAULT.bold().foreground(AttributedStyle.RED);
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/HeadAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/HeadAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/HeadAction.java
deleted file mode 100644
index ad144d4..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/HeadAction.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Command(scope = "shell", name = "head", description = "Displays the first lines of a file.")
-@Service
-public class HeadAction implements Action {
-
-    private static final int DEFAULT_NUMBER_OF_LINES = 10;
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    @Option(name = "-n", aliases = {}, description = "The number of lines to display, starting at 1.", required = false, multiValued = false)
-    private int numberOfLines;
-
-    @Argument(index = 0, name = "paths or urls", description = "A list of file paths or urls to display separated by whitespaces.", required = false, multiValued = true)
-    private List<String> paths;
-
-    @Override
-    public Object execute() throws Exception {
-        //If no paths provided assume standar input
-        if (paths == null || paths.size() == 0) {
-            if (log.isDebugEnabled()) {
-                log.debug("Heading STDIN");
-            }
-
-            head(new BufferedReader(new InputStreamReader(System.in)));
-        } else {
-            for (String filename : paths) {
-                BufferedReader reader;
-
-                // First try a URL
-                try {
-                    URL url = new URL(filename);
-                    if (log.isDebugEnabled()) {
-                        log.debug("Heading URL: " + url);
-                    }
-                    reader = new BufferedReader(new InputStreamReader(url.openStream()));
-                }
-                catch (MalformedURLException ignore) {
-                    // They try a file
-                    File file = new File(filename);
-                    if (log.isDebugEnabled()) {
-                        log.debug("Heading file: " + file);
-                    }
-                    reader = new BufferedReader(new FileReader(file));
-                }
-
-                try {
-                    head(reader);
-                }
-                finally {
-                    try {
-                        reader.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-            }
-        }
-        return null;
-    }
-
-    private void head(final BufferedReader reader) throws IOException {
-        String line;
-        int lineno = 1;
-
-        if (numberOfLines < 1) {
-            numberOfLines = DEFAULT_NUMBER_OF_LINES;
-        }
-
-        while ((line = reader.readLine()) != null && lineno <= numberOfLines) {
-            System.out.println(line);
-            lineno++;
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/HistoryAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/HistoryAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/HistoryAction.java
deleted file mode 100644
index f4b0157..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/HistoryAction.java
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.History;
-import org.apache.karaf.shell.support.ansi.SimpleAnsi;
-
-/**
- * History command
- */
-@Command(scope = "shell", name="history", description="Prints command history.")
-@Service
-public class HistoryAction implements Action {
-
-    @Option(name = "-c", aliases = { "--clear" }, description = "Clears the shell command history.", required = false, multiValued = false)
-    private boolean clear;
-
-    @Reference
-    History history;
-
-    @Override
-    public Object execute() throws Exception {
-        if (history != null) {
-            if (clear) {
-                history.clear();
-            } else {
-                for (int index = history.first(); index <= history.last(); index++) {
-                    System.out.println(
-                            "  " + SimpleAnsi.INTENSITY_BOLD + String.format("%3d", index) + SimpleAnsi.INTENSITY_NORMAL
-                                    + "  " + history.get(index));
-                }
-            }
-        }
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/IfAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/IfAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/IfAction.java
deleted file mode 100644
index 3c1362f..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/IfAction.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Function;
-import org.apache.karaf.shell.api.console.Session;
-
-/**
- * Execute a closure on a list of arguments.
- */
-@Command(scope = "shell", name = "if", description = "If/Then/Else block.")
-@Service
-public class IfAction implements Action {
-
-    @Argument(name = "condition", index = 0, multiValued = false, required = true, description = "The condition")
-    Function condition;
-
-    @Argument(name = "ifTrue", index = 1, multiValued = false, required = true, description = "The function to execute if the condition is true")
-    Function ifTrue;
-
-    @Argument(name = "ifFalse", index = 2, multiValued = false, required = false, description = "The function to execute if the condition is false")
-    Function ifFalse;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        Object result = condition.execute(session, null);
-        if (isTrue(result)) {
-            return ifTrue.execute(session, null);
-        } else {
-            if (ifFalse != null) {
-                return ifFalse.execute(session, null);
-            }
-        }
-        return null;
-    }
-
-    private boolean isTrue(Object result) {
-        if (result == null) {
-            return false;
-        }
-        if (result instanceof String && ((String) result).equals("")) {
-            return false;
-        }
-        if (result instanceof Number) {
-            return ((Number) result).doubleValue() != 0.0d;
-        }
-        if (result instanceof Boolean) {
-            return (Boolean) result;
-        }
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java
deleted file mode 100644
index 0479ba8..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/LessAction.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.jline.builtins.Less;
-import org.jline.builtins.Source;
-import org.jline.builtins.Source.StdInSource;
-import org.jline.builtins.Source.URLSource;
-import org.jline.terminal.Terminal;
-
-@Command(scope = "shell", name = "less", description = "File pager.")
-@Service
-public class LessAction implements Action {
-
-    @Option(name = "-e", aliases = "--quit-at-eof")
-    boolean quitAtSecondEof;
-
-    @Option(name = "-E", aliases = "--QUIT-AT-EOF")
-    boolean quitAtFirstEof;
-
-    @Option(name = "-N", aliases = "--LINE-NUMBERS")
-    boolean printLineNumbers;
-
-    @Option(name = "-q", aliases = {"--quiet", "--silent"})
-    boolean quiet;
-
-    @Option(name = "-Q", aliases = {"--QUIET", "--SILENT"})
-    boolean veryQuiet;
-
-    @Option(name = "-S", aliases = "--chop-long-lines")
-    boolean chopLongLines;
-
-    @Option(name = "-i", aliases = "--ignore-case")
-    boolean ignoreCaseCond;
-
-    @Option(name = "-I", aliases = "--IGNORE-CASE")
-    boolean ignoreCaseAlways;
-
-    @Option(name = "-x", aliases = "--tabs")
-    int tabs = 4;
-
-    @Argument(multiValued = true)
-    List<String> files;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        Terminal terminal = (Terminal) session.get(".jline.terminal");
-        Less less = new Less(terminal);
-        less.quitAtFirstEof = quitAtFirstEof;
-        less.quitAtSecondEof = quitAtSecondEof;
-        less.quiet = quiet;
-        less.veryQuiet = veryQuiet;
-        less.chopLongLines = chopLongLines;
-        less.ignoreCaseAlways = ignoreCaseAlways;
-        less.ignoreCaseCond = ignoreCaseCond;
-        less.tabs = tabs;
-        less.printLineNumbers = printLineNumbers;
-        List<Source> sources = new ArrayList<>();
-        if (files == null || files.isEmpty()) {
-            files = Collections.singletonList("-");
-        }
-        Path pwd = Paths.get(System.getProperty("karaf.home", System.getProperty("user.dir")));
-        for (String arg : files) {
-            if ("-".equals(arg)) {
-                sources.add(new StdInSource());
-            } else {
-                sources.add(new URLSource(pwd.toUri().resolve(arg).toURL(), arg));
-            }
-        }
-        less.run(sources);
-        return null;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java
deleted file mode 100644
index ef92105..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/MoreAction.java
+++ /dev/null
@@ -1,144 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.lang.reflect.Method;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.api.console.Terminal;
-import org.apache.karaf.shell.support.ansi.AnsiSplitter;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Command(scope = "shell", name = "more", description = "File pager.")
-@Service
-public class MoreAction implements Action {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    @Option(name = "--lines", description = "stop after N lines")
-    int lines;
-
-    @Reference(optional = true)
-    Terminal terminal;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        if (terminal == null || !isTty(System.out)) {
-            BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
-            String line;
-            while ((line = reader.readLine()) != null) {
-                System.out.println(line);
-                checkInterrupted();
-            }
-            return null;
-        } else {
-            boolean echo = terminal.isEchoEnabled();
-            terminal.setEchoEnabled(false);
-            try {
-                if (lines == 0) {
-                    lines = terminal.getHeight();
-                }
-                AnsiSplitter.AnsiBufferedReader reader = AnsiSplitter.splitter(System.in, terminal.getWidth(), 4);
-                int count = 0;
-                int c;
-                do {
-                    do {
-                        String line;
-                        if ((line = reader.readLine()) == null) {
-                            return null;
-                        }
-                        System.out.println(line);
-                        checkInterrupted();
-                    } while (++count < lines - 2);
-                    c = -1;
-                    while (c == -1) {
-                        System.out.flush();
-                        System.out.print("--More--");
-                        System.out.flush();
-                        c = session.getKeyboard().read();
-                        switch (c) {
-                            case 'q':
-                            case -1:
-                                c = 'q';
-                                break;
-                            case '\r':
-                            case '\n':
-                            case 14: // Down arrow
-                                count--;
-                                System.out.print("\r          \r");
-                                break;
-                            case ' ':
-                                count = 0;
-                                System.out.print("\r          \r");
-                                break;
-                            case 16: // Up arrow
-                                // fall through
-                            default:
-                                c = -1;
-                                System.out.print("\r          \r");
-                                break;
-                        }
-                        if (c == 'q') {
-                            break;
-                        }
-                    }
-                } while (c != 'q');
-            } catch (InterruptedException ie) {
-            	log.debug("Interrupted by user");
-            } finally {
-                terminal.setEchoEnabled(echo);
-            }
-        }
-        return null;
-    }
-
-    protected boolean isTty(OutputStream out) {
-        try {
-            Method mth = out.getClass().getDeclaredMethod("getCurrent");
-            mth.setAccessible(true);
-            Object current = mth.invoke(out);
-            return current == session.getConsole();
-        } catch (Throwable t) {
-            return false;
-        }
-    }
-
-    /**
-     * This is for long running commands to be interrupted by ctrl-c.
-     *
-     * @throws InterruptedException If the command is interrupted.
-     */
-    public static void checkInterrupted() throws InterruptedException {
-        Thread.yield();
-        if (Thread.currentThread().isInterrupted()) {
-            throw new InterruptedException();
-        }
-    }
-
-}


[2/3] karaf git commit: [KARAF-397] Allow completion of non Karaf based osgi commands [KARAF-2454] Portable way to make custom shell commands

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/NewAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/NewAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/NewAction.java
deleted file mode 100644
index 6173ca2..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/NewAction.java
+++ /dev/null
@@ -1,379 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.lang.reflect.Array;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Type;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.support.converter.DefaultConverter;
-import org.apache.karaf.shell.support.converter.GenericType;
-import org.apache.karaf.shell.support.converter.ReifiedType;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.wiring.BundleCapability;
-import org.osgi.framework.wiring.BundleRevision;
-import org.osgi.framework.wiring.BundleWiring;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Instantiate a new object
- */
-@Command(scope = "shell", name = "new", description = "Creates a new java object.")
-@Service
-@SuppressWarnings("rawtypes")
-public class NewAction implements Action {
-    private static final Logger LOG = LoggerFactory.getLogger(NewAction.class);
-    @Argument(name = "class", index = 0, multiValued = false, required = true, description = "FQN of the class to load")
-    String clazzName;
-
-    @Argument(name = "args", index = 1, multiValued = true, required = false, description = "Constructor arguments")
-    List<Object> args;
-
-    boolean reorderArguments;
-
-    protected DefaultConverter converter;
-    
-    @Reference
-    BundleContext context;
-
-    @Override
-    public Object execute() throws Exception {
-        if (args == null) {
-            args = Collections.emptyList();
-        }
-        String packageName = getPackageName(clazzName);
-        Bundle bundle = getBundleOfferingPackage(packageName);
-        LOG.info("Using bundle {} classloader to load {}.", bundle.getSymbolicName(), clazzName);
-        ClassLoader classLoader = getClassLoader(bundle);
-        converter = new DefaultConverter(classLoader);
-        Class<?> clazz = (Class<?>)converter.convert(clazzName, Class.class);
-        // Handle arrays
-        if (clazz.isArray()) {
-            Object obj = Array.newInstance(clazz.getComponentType(), args.size());
-            for (int i = 0; i < args.size(); i++) {
-                Array.set(obj, i, convert(args.get(i), clazz.getComponentType()));
-            }
-            return obj;
-        }
-
-        // Map of matching constructors
-        Map<Constructor, List<Object>> matches = findMatchingConstructors(clazz, args, Arrays.asList(new ReifiedType[args.size()]));
-        if (matches.size() == 1) {
-            try {
-                Map.Entry<Constructor, List<Object>> match = matches.entrySet().iterator().next();
-                return newInstance(match.getKey(), match.getValue().toArray());
-            } catch (Throwable e) {
-                throw new Exception("Error when instantiating object of class " + clazz.getName(), getRealCause(e));
-            }
-        } else if (matches.size() == 0) {
-            throw new Exception("Unable to find a matching constructor on class " + clazz.getName() + " for arguments " + args + " when instantiating object.");
-        } else {
-            throw new Exception("Multiple matching constructors found on class " + clazz.getName() + " for arguments " + args + " when instantiating object: " + matches.keySet());
-        }
-    }
-
-    private String getPackageName(String name) {
-        int nameSeperator = name.lastIndexOf(".");
-        if (nameSeperator <= 0) {
-            return null;
-        }
-        return name.substring(0, nameSeperator);
-    }
-
-    /**
-     * Get class loader offering a named package. This only works if we do not care
-     * which package we get in case of several package versions
-     *  
-     * @param reqPackageName
-     * @return
-     */
-    private Bundle getBundleOfferingPackage(String reqPackageName) {
-        Bundle[] bundles = context.getBundles();
-        for (Bundle bundle : bundles) {
-            BundleRevision rev = bundle.adapt(BundleRevision.class);
-            if (rev != null) {
-                List<BundleCapability> caps = rev.getDeclaredCapabilities(BundleRevision.PACKAGE_NAMESPACE);
-                for (BundleCapability cap : caps) {
-                    Map<String, Object> attr = cap.getAttributes();
-                    String packageName = (String)attr.get(BundleRevision.PACKAGE_NAMESPACE);
-                    if (packageName.equals(reqPackageName)) {
-                        return bundle;
-                    }
-                }
-            }
-        }
-        return context.getBundle(0);
-    }
-
-    private ClassLoader getClassLoader(Bundle bundle) {
-        BundleWiring wiring = bundle.adapt(BundleWiring.class);
-        return wiring.getClassLoader();
-    }
-
-    //
-    // Code below comes from Aries blueprint implementation.  Given this code is not available
-    // from a public API it has been copied here.
-    //
-    private Object newInstance(Constructor constructor, Object... args) throws Exception {
-        return constructor.newInstance(args);
-    }
-
-    private Map<Constructor, List<Object>> findMatchingConstructors(Class type, List<Object> args, List<ReifiedType> types) {
-        Map<Constructor, List<Object>> matches = new HashMap<Constructor, List<Object>>();
-        // Get constructors
-        List<Constructor> constructors = new ArrayList<Constructor>(Arrays.asList(type.getConstructors()));
-        // Discard any signature with wrong cardinality
-        for (Iterator<Constructor> it = constructors.iterator(); it.hasNext();) {
-            if (it.next().getParameterTypes().length != args.size()) {
-                it.remove();
-            }
-        }
-        // Find a direct match with assignment
-        if (matches.size() != 1) {
-            Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
-            for (Constructor cns : constructors) {
-                boolean found = true;
-                List<Object> match = new ArrayList<Object>();
-                for (int i = 0; i < args.size(); i++) {
-                    ReifiedType argType = new GenericType(cns.getGenericParameterTypes()[i]);
-                    if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
-                        found = false;
-                        break;
-                    }
-                    if (!isAssignable(args.get(i), argType)) {
-                        found = false;
-                        break;
-                    }
-                    try {
-                        match.add(convert(args.get(i), cns.getGenericParameterTypes()[i]));
-                    } catch (Throwable t) {
-                        found = false;
-                        break;
-                    }
-                }
-                if (found) {
-                    nmatches.put(cns, match);
-                }
-            }
-            if (nmatches.size() > 0) {
-                matches = nmatches;
-            }
-        }
-        // Find a direct match with conversion
-        if (matches.size() != 1) {
-            Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
-            for (Constructor cns : constructors) {
-                boolean found = true;
-                List<Object> match = new ArrayList<Object>();
-                for (int i = 0; i < args.size(); i++) {
-                    ReifiedType argType = new GenericType(cns.getGenericParameterTypes()[i]);
-                    if (types.get(i) != null && !argType.getRawClass().equals(types.get(i).getRawClass())) {
-                        found = false;
-                        break;
-                    }
-                    try {
-                        Object val = convert(args.get(i), argType);
-                        match.add(val);
-                    } catch (Throwable t) {
-                        found = false;
-                        break;
-                    }
-                }
-                if (found) {
-                    nmatches.put(cns, match);
-                }
-            }
-            if (nmatches.size() > 0) {
-                matches = nmatches;
-            }
-        }
-        // Start reordering with assignment
-        if (matches.size() != 1 && reorderArguments && args.size() > 1) {
-            Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
-            for (Constructor cns : constructors) {
-                ArgumentMatcher matcher = new ArgumentMatcher(cns.getGenericParameterTypes(), false);
-                List<Object> match = matcher.match(args, types);
-                if (match != null) {
-                    nmatches.put(cns, match);
-                }
-            }
-            if (nmatches.size() > 0) {
-                matches = nmatches;
-            }
-        }
-        // Start reordering with conversion
-        if (matches.size() != 1 && reorderArguments && args.size() > 1) {
-            Map<Constructor, List<Object>> nmatches = new HashMap<Constructor, List<Object>>();
-            for (Constructor cns : constructors) {
-                ArgumentMatcher matcher = new ArgumentMatcher(cns.getGenericParameterTypes(), true);
-                List<Object> match = matcher.match(args, types);
-                if (match != null) {
-                    nmatches.put(cns, match);
-                }
-            }
-            if (nmatches.size() > 0) {
-                matches = nmatches;
-            }
-        }
-        return matches;
-    }
-
-    protected Object convert(Object obj, Type type) throws Exception {
-        return converter.convert(obj, new GenericType(type));
-    }
-
-    protected Object convert(Object obj, ReifiedType type) throws Exception {
-        return converter.convert(obj, type);
-    }
-
-    @SuppressWarnings("unchecked")
-    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 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 static Object UNMATCHED = new Object();
-
-    private class ArgumentMatcher {
-
-        private List<TypeEntry> entries;
-        private boolean convert;
-
-        public ArgumentMatcher(Type[] types, boolean convert) {
-            entries = new ArrayList<TypeEntry>();
-            for (Type type : types) {
-                entries.add(new TypeEntry(new GenericType(type)));
-            }
-            this.convert = convert;
-        }
-
-        public List<Object> match(List<Object> arguments, List<ReifiedType> forcedTypes) {
-            if (find(arguments, forcedTypes)) {
-                return getArguments();
-            }
-            return null;
-        }
-
-        private List<Object> getArguments() {
-            List<Object> list = new ArrayList<Object>();
-            for (TypeEntry entry : entries) {
-                if (entry.argument == UNMATCHED) {
-                    throw new RuntimeException("There are unmatched types");
-                } else {
-                    list.add(entry.argument);
-                }
-            }
-            return list;
-        }
-
-        private boolean find(List<Object> arguments, List<ReifiedType> forcedTypes) {
-            if (entries.size() == arguments.size()) {
-                boolean matched = true;
-                for (int i = 0; i < arguments.size() && matched; i++) {
-                    matched = find(arguments.get(i), forcedTypes.get(i));
-                }
-                return matched;
-            }
-            return false;
-        }
-
-        private boolean find(Object arg, ReifiedType forcedType) {
-            for (TypeEntry entry : entries) {
-                Object val = arg;
-                if (entry.argument != UNMATCHED) {
-                    continue;
-                }
-                if (forcedType != null) {
-                    if (!forcedType.equals(entry.type)) {
-                        continue;
-                    }
-                } else if (arg != null) {
-                    if (convert) {
-                        try {
-                            // TODO: call canConvert instead of convert()
-                            val = convert(arg, entry.type);
-                        } catch (Throwable t) {
-                            continue;
-                        }
-                    } else {
-                        if (!isAssignable(arg, entry.type)) {
-                            continue;
-                        }
-                    }
-                }
-                entry.argument = val;
-                return true;
-            }
-            return false;
-        }
-
-    }
-
-    private static class TypeEntry {
-
-        private final ReifiedType type;
-        private Object argument;
-
-        public TypeEntry(ReifiedType type) {
-            this.type = type;
-            this.argument = UNMATCHED;
-        }
-
-    }
-
-    public static Throwable getRealCause(Throwable t) {
-        if (t instanceof InvocationTargetException && t.getCause() != null) {
-            return t.getCause();
-        }
-        return t;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/SleepAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/SleepAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/SleepAction.java
deleted file mode 100644
index e8b1103..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/SleepAction.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Command(scope = "shell", name = "sleep", description = "Sleeps for a bit then wakes up.")
-@Service
-public class SleepAction implements Action {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    @Argument(index = 0, name = "duration", description = "The amount of time to sleep. The default time unit is millisecond, use -s option to use second instead.", required = true, multiValued = false)
-    private long time = -1;
-    
-    @Option(name = "-s", aliases = { "--second" }, description = "Use a duration time in seconds instead of milliseconds.", required = false, multiValued = false)
-    private boolean second = false;
-
-    @Override
-    public Object execute() throws Exception {
-        if (second) {
-            log.info("Sleeping for {} second(s)", time);
-            time = time * 1000;
-        } else {
-            log.info("Sleeping for {} millisecond(s)", time);
-        }
-
-        try {
-            Thread.sleep(time);
-        }
-        catch (InterruptedException ignore) {
-            log.debug("Sleep was interrupted... :-(");
-        }
-
-        log.info("Awake now");
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/SortAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/SortAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/SortAction.java
deleted file mode 100644
index 4b9d165..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/SortAction.java
+++ /dev/null
@@ -1,404 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Sort lines of text
- */
-@Command(scope = "shell", name = "sort", description = "Writes sorted concatenation of all files to standard output.")
-@Service
-public class SortAction implements Action {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    @Option(name = "-f", aliases = { "-ignore-case" }, description = "fold lower case to upper case characters", required = false, multiValued = false)
-    private boolean caseInsensitive;
-
-    @Option(name = "-r", aliases = { "--reverse" }, description = "reverse the result of comparisons", required = false, multiValued = false)
-    private boolean reverse;
-
-    @Option(name = "-u", aliases = { "--unique" }, description = "output only the first of an equal run", required = false, multiValued = false)
-    private boolean unique;
-
-    @Option(name = "-t", aliases = { "--field-separator" }, description = "use SEP instead of non-blank to blank transition", required = false, multiValued = false)
-    private String separator;
-
-    @Option(name = "-b", aliases = { "--ignore-leading-blanks" }, description = "ignore leading blanks", required = false, multiValued = false)
-    private boolean ignoreBlanks;
-
-    @Option(name = "-k", aliases = { "--key" }, description = "Fields to use for sorting separated by whitespaces", required = false, multiValued = true)
-    private List<String> sortFields;
-
-    @Option(name = "-n", aliases = { "--numeric-sort" }, description = "compare according to string numerical value", required = false, multiValued = false)
-    private boolean numeric;
-
-    @Argument(index = 0, name = "files", description = "A list of files separated by whitespaces", required = false, multiValued = true)
-    private List<String> paths;
-
-    @Override
-    public Object execute() throws Exception {
-        if (paths != null && paths.size() > 0) {
-            List<String> lines = new ArrayList<String>();
-            for (String filename : paths) {
-                BufferedReader reader;
-
-                // First try a URL
-                try {
-                    URL url = new URL(filename);
-                    log.info("Printing URL: " + url);
-                    reader = new BufferedReader(new InputStreamReader(url.openStream()));
-                }
-                catch (MalformedURLException ignore) {
-                    // They try a file
-                    File file = new File(filename);
-                    log.info("Printing file: " + file);
-                    reader = new BufferedReader(new FileReader(file));
-                }
-
-                try {
-                    read(reader, lines);
-                }
-                finally {
-                    try {
-                        reader.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-            }
-            sort(lines, System.out);
-        }
-        else {
-            sort(System.in, System.out);
-        }
-        return null;
-    }
-
-    protected void read(BufferedReader r, List<String> lines) throws Exception {
-        for (String s = r.readLine(); s != null; s = r.readLine()) {
-            lines.add(s);
-        }
-    }
-
-    protected void sort(InputStream input, PrintStream out) throws Exception {
-        List<String> strings = new ArrayList<String>();
-        BufferedReader r = new BufferedReader(new InputStreamReader(input));
-        read(r, strings);
-        sort(strings, out);
-    }
-
-    protected void sort(List<String> strings, PrintStream out) throws Exception {
-        char sep = (separator == null || separator.length() == 0) ? '\0' : separator.charAt(0);
-        Collections.sort(strings, new SortComparator(caseInsensitive, reverse, ignoreBlanks, numeric, sep, sortFields));
-        String last = null;
-        for (String s : strings) {
-            if (!unique || last == null || !s.equals(last)) {
-                out.println(s);
-            }
-            last = s;
-        }
-    }
-
-    public static class SortComparator implements Comparator<String> {
-
-        private boolean caseInsensitive;
-        private boolean reverse;
-        private boolean ignoreBlanks;
-        private boolean numeric;
-        private char separator;
-        private List<Key> sortKeys;
-
-        private static Pattern fpPattern;
-        static {
-            final String Digits     = "(\\p{Digit}+)";
-            final String HexDigits  = "(\\p{XDigit}+)";
-            final String Exp        = "[eE][+-]?" + Digits;
-            final String fpRegex    = "([\\x00-\\x20]*[+-]?(NaN|Infinity|(((" + Digits + "(\\.)?(" + Digits + "?)(" + Exp + ")?)|(\\.(" + Digits + ")(" + Exp + ")?)|(((0[xX]" + HexDigits + "(\\.)?)|(0[xX]" + HexDigits + "?(\\.)" + HexDigits + "))[pP][+-]?" + Digits + "))" + "[fFdD]?))[\\x00-\\x20]*)(.*)";
-            fpPattern = Pattern.compile(fpRegex);
-        }
-
-        public SortComparator(boolean caseInsensitive,
-                              boolean reverse,
-                              boolean ignoreBlanks,
-                              boolean numeric,
-                              char separator,
-                              List<String> sortFields) {
-            this.caseInsensitive = caseInsensitive;
-            this.reverse = reverse;
-            this.separator = separator;
-            this.ignoreBlanks = ignoreBlanks;
-            this.numeric = numeric;
-            if (sortFields == null || sortFields.size() == 0) {
-                sortFields = new ArrayList<String>();
-                sortFields.add("1");
-            }
-            sortKeys = new ArrayList<Key>();
-            for (String f : sortFields) {
-                sortKeys.add(new Key(f));
-            }
-        }
-
-        public int compare(String o1, String o2) {
-            int res = 0;
-
-            List<Integer> fi1 = getFieldIndexes(o1);
-            List<Integer> fi2 = getFieldIndexes(o2);
-            for (Key key : sortKeys) {
-                int[] k1 = getSortKey(o1, fi1, key);
-                int[] k2 = getSortKey(o2, fi2, key);
-                if (key.numeric) {
-                    Double d1 = getDouble(o1, k1[0], k1[1]);
-                    Double d2 = getDouble(o2, k2[0], k2[1]);
-                    res = d1.compareTo(d2);
-                } else {
-                    res = compareRegion(o1, k1[0], k1[1], o2, k2[0], k2[1], key.caseInsensitive);
-                }
-                if (res != 0) {
-                    if (key.reverse) {
-                        res = - res;
-                    }
-                    break;
-                }
-            }
-            return res;
-        }
-
-        protected Double getDouble(String s, int start, int end) {
-            Matcher m = fpPattern.matcher(s.substring(start, end));
-            m.find();
-            return new Double(s.substring(0, m.end(1)));
-        }
-
-        protected int compareRegion(String s1, int start1, int end1, String s2, int start2, int end2, boolean caseInsensitive) {
-            int n1 = end1, n2 = end2;
-            for (int i1 = start1, i2 = start2; i1 < end1 && i2 < n2; i1++, i2++) {
-                char c1 = s1.charAt(i1);
-                char c2 = s2.charAt(i2);
-                if (c1 != c2) {
-                    if (caseInsensitive) {
-                        c1 = Character.toUpperCase(c1);
-                        c2 = Character.toUpperCase(c2);
-                        if (c1 != c2) {
-                            c1 = Character.toLowerCase(c1);
-                            c2 = Character.toLowerCase(c2);
-                            if (c1 != c2) {
-                                return c1 - c2;
-                            }
-                        }
-                    } else {
-                        return c1 - c2;
-                    }
-                }
-            }
-            return n1 - n2;
-        }
-
-        protected int[] getSortKey(String str, List<Integer> fields, Key key) {
-            int start;
-            int end;
-            if (key.startField * 2 <= fields.size()) {
-                start = fields.get((key.startField - 1) * 2);
-                if (key.ignoreBlanksStart) {
-                    while (start < fields.get((key.startField - 1) * 2 + 1) && Character.isWhitespace(str.charAt(start))) {
-                        start++;
-                    }
-                }
-                if (key.startChar > 0) {
-                    start = Math.min(start + key.startChar - 1, fields.get((key.startField - 1) * 2 + 1));
-                }
-            } else {
-                start = 0;
-            }
-            if (key.endField > 0 && key.endField * 2 <= fields.size()) {
-                end =  fields.get((key.endField - 1) * 2);
-                if (key.ignoreBlanksEnd) {
-                    while (end < fields.get((key.endField - 1) * 2 + 1) && Character.isWhitespace(str.charAt(end))) {
-                        end++;
-                    }
-                }
-                if (key.endChar > 0) {
-                    end = Math.min(end + key.endChar - 1, fields.get((key.endField - 1) * 2 + 1));
-                }
-            } else {
-                end = str.length();
-            }
-            return new int[] { start, end };
-        }
-
-        protected List<Integer> getFieldIndexes(String o) {
-            List<Integer> fields = new ArrayList<Integer>();
-            if (o.length() > 0) {
-                if (separator == '\0') {
-                    int i = 0;
-                    fields.add(0);
-                    for (int idx = 1; idx < o.length(); idx++) {
-                        if (Character.isWhitespace(o.charAt(idx)) && !Character.isWhitespace(o.charAt(idx - 1))) {
-                            fields.add(idx - 1);
-                            fields.add(idx);
-                        }
-                    }
-                    fields.add(o.length() - 1);
-                } else {
-                    int last = -1;
-                    for (int idx = o.indexOf(separator); idx >= 0; idx = o.indexOf(separator, idx + 1)) {
-                        if (last >= 0) {
-                            fields.add(last);
-                            fields.add(idx - 1);
-                        } else if (idx > 0) {
-                            fields.add(0);
-                            fields.add(idx - 1);
-                        }
-                        last = idx + 1;
-                    }
-                    if (last < o.length()) {
-                        fields.add(last < 0 ? 0 : last);
-                        fields.add(o.length() - 1);
-                    }
-                }
-            }
-            return fields;
-        }
-
-        public class Key {
-            int startField;
-            int startChar;
-            int endField;
-            int endChar;
-            boolean ignoreBlanksStart;
-            boolean ignoreBlanksEnd;
-            boolean caseInsensitive;
-            boolean reverse;
-            boolean numeric;
-
-            public Key(String str) {
-                boolean modifiers = false;
-                boolean startPart = true;
-                boolean inField = true;
-                boolean inChar = false;
-                for (char c : str.toCharArray()) {
-                    switch (c) {
-                        case '0':
-                        case '1':
-                        case '2':
-                        case '3':
-                        case '4':
-                        case '5':
-                        case '6':
-                        case '7':
-                        case '8':
-                        case '9':
-                            if (!inField && !inChar) {
-                                throw new IllegalArgumentException("Bad field syntax: " + str);
-                            }
-                            if (startPart) {
-                                if (inChar) {
-                                    startChar = startChar * 10 + (c - '0');
-                                } else {
-                                    startField = startField * 10 + (c - '0');
-                                }
-                            } else {
-                                if (inChar) {
-                                    endChar = endChar * 10 + (c - '0');
-                                } else {
-                                    endField = endField * 10 + (c - '0');
-                                }
-                            }
-                            break;
-                        case '.':
-                            if (!inField) {
-                                throw new IllegalArgumentException("Bad field syntax: " + str);
-                            }
-                            inField = false;
-                            inChar = true;
-                            break;
-                        case 'n':
-                            inField = false;
-                            inChar = false;
-                            modifiers = true;
-                            numeric = true;
-                            break;
-                        case 'f':
-                            inField = false;
-                            inChar = false;
-                            modifiers = true;
-                            caseInsensitive = true;
-                            break;
-                        case 'r':
-                            inField = false;
-                            inChar = false;
-                            modifiers = true;
-                            reverse = true;
-                            break;
-                        case 'b':
-                            inField = false;
-                            inChar = false;
-                            modifiers = true;
-                            if (startPart) {
-                                ignoreBlanksStart = true;
-                            } else {
-                                ignoreBlanksEnd = true;
-                            }
-                            break;
-                        case ',':
-                            inField = true;
-                            inChar = false;
-                            startPart = false;
-                            break;
-                        default:
-                            throw new IllegalArgumentException("Bad field syntax: " + str);
-                    }
-                }
-                if (!modifiers) {
-                    ignoreBlanksStart = ignoreBlanksEnd = SortComparator.this.ignoreBlanks;
-                    reverse = SortComparator.this.reverse;
-                    caseInsensitive = SortComparator.this.caseInsensitive;
-                    numeric = SortComparator.this.numeric;
-                }
-                if (startField < 1) {
-                    throw new IllegalArgumentException("Bad field syntax: " + str);
-                }
-            }
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/TacAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/TacAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/TacAction.java
deleted file mode 100644
index 5cf1b20..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/TacAction.java
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.io.StringWriter;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.io.File;
-import java.io.BufferedWriter;
-import java.io.FileOutputStream;
-import java.io.OutputStreamWriter;
-import java.io.Writer;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-/**
- * Grab the text from the standard input and return it as a string.
- * Also write this text to a file if specified
- */
-@Command(scope = "shell", name = "tac", description = "Captures the STDIN and returns it as a string. Optionally writes the content to a file.")
-@Service
-public class TacAction implements Action {
-
-    @Option(name = "-f", aliases = {}, description = "Outputs the content to the given file", required = false, multiValued = false)
-    private File file;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        StringWriter sw = new StringWriter();
-        Writer[] writers;
-        if (file != null) {
-            writers = new Writer[] { sw, new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file))) };
-        } else {
-            writers = new Writer[] { sw };
-        }
-        BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in));
-        String s = rdr.readLine();
-        boolean first = true;
-        while (s != null)
-        {
-            for (Writer w : writers) {
-                if (!first) {
-                    w.write("\n");
-                }
-                w.write(s);
-            }
-            first = false;
-            s = rdr.readLine();
-        }
-        for (Writer w : writers) {
-            w.close();
-        }
-        return sw.toString();
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/TailAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/TailAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/TailAction.java
deleted file mode 100644
index 435816c..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/TailAction.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.util.LinkedList;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-@Command(scope = "shell", name = "tail", description = "Displays the last lines of a file.")
-@Service
-public class TailAction implements Action {
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
-
-    private static final int DEFAULT_NUMBER_OF_LINES = 10;
-
-    private static final int DEFAULT_SLEEP_INTERVAL = 200;
-
-    @Option(name = "-n", aliases = {}, description = "The number of lines to display, starting at 1.", required = false, multiValued = false)
-    private int numberOfLines;
-
-    @Option(name = "-f", aliases = {}, description = "Follow file changes", required = false, multiValued = false)
-    private boolean continuous;
-
-    @Option(name = "-s", aliases = {}, description = "Sleep interval (used for follow)", required = false, multiValued = false)
-    private long sleepInterval;
-
-    @Argument(index = 0, name = "path or url", description = "A file path or url to display.", required = false, multiValued = false)
-    private String path;
-
-    @Override
-    public Object execute() throws Exception {
-        //If no paths provided assume standar input
-        if (path == null || path.trim().length() == 0) {
-            if (log.isDebugEnabled()) {
-                log.debug("Tailing STDIN");
-            }
-            tail(new BufferedReader(new InputStreamReader(System.in)));
-        } else {
-            BufferedReader reader;
-
-            // First try a URL
-            try {
-                URL url = new URL(path);
-                if (log.isDebugEnabled()) {
-                    log.debug("Tailing URL: " + url);
-                }
-                reader = new BufferedReader(new InputStreamReader(url.openStream()));
-            }
-            catch (MalformedURLException ignore) {
-                // They try a file
-                File file = new File(path);
-                if (log.isDebugEnabled()) {
-                    log.debug("Tailing file: " + file);
-                }
-                reader = new BufferedReader(new FileReader(file));
-            }
-
-            try {
-                tail(reader);
-            }
-            finally {
-                try {
-                    reader.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-        return null;
-    }
-
-    /**
-     * prints the tail of the file / url
-     * 
-     * @param reader
-     * @throws IOException
-     */
-    private void tail(final BufferedReader reader) throws InterruptedException, IOException {
-        
-        if (numberOfLines < 1) {
-            numberOfLines = DEFAULT_NUMBER_OF_LINES;
-        }
-        if (sleepInterval < 1) {
-            sleepInterval = DEFAULT_SLEEP_INTERVAL;
-        }
-        
-        LinkedList<String> lines = new LinkedList<String>();
-        String line;
-        while ((line = reader.readLine()) != null) {
-            lines.add(line);
-            if (lines.size() > numberOfLines) {
-                lines.removeFirst();
-            }
-        }
-
-        for (String l : lines) {
-            System.out.println(l);
-        }
-
-        //If command is running as continuous
-        while (continuous) {
-            Thread.sleep(sleepInterval);
-            while ((line = reader.readLine()) != null) {
-                System.out.println(line);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/WcAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/WcAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/WcAction.java
deleted file mode 100644
index 4a063f8..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/WcAction.java
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.Option;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-
-import java.io.*;
-import java.util.List;
-
-@Command(scope = "shell", name = "wc", description = "Print newline, word, and byte counts for each file.")
-@Service
-public class WcAction implements Action {
-
-    @Option(name = "-l", aliases = { "--lines" }, description = "Print the newline counts.", required = false, multiValued = false)
-    private boolean lines;
-
-    @Option(name = "-w", aliases = { "--words" }, description = "Print the word counts.", required = false, multiValued = false)
-    private boolean words;
-
-    @Option(name = "-m", aliases = { "--chars" }, description = "Print the character counts.", required = false, multiValued = false)
-    private boolean chars;
-
-    @Option(name = "-c", aliases = { "--bytes" }, description = "Print the byte counts.", required = false, multiValued = false)
-    private boolean bytes;
-
-    @Argument(index = 0, name = "files", description = "The list of files where to perform the count", required = false, multiValued = true)
-    private List<File> files;
-
-    @Override
-    public Object execute() throws Exception {
-        this.setDefaultOptions();
-
-        String outputString;
-
-        if (files == null) {
-            WordCounts wordCounts = getWordCounts(System.in);
-            outputString = formatWordCounts(wordCounts, null);
-        } else {
-            outputString = getFilesWordCountReport(files);
-        }
-
-        System.out.println(outputString);
-        return null;
-    }
-
-    /**
-     * Create a combined word count report of the required files.
-     * If there are more than one file supplied, a total row will be added.
-     *
-     * @param files the list of files.
-     * @return the word count report String.
-     * @throws IOException in case of a count failure.
-     */
-    protected String getFilesWordCountReport(List<File> files) throws IOException {
-        StringBuilder stringBuilder = new StringBuilder();
-        WordCounts totalWordCounts = new WordCounts();
-        for (File file : files) {
-            WordCounts fileWordCount = getWordCounts(new FileInputStream(file));
-            String fileFormattedString = formatWordCounts(fileWordCount, file.getName());
-            // add it to the running total which will be outputted at the end
-            totalWordCounts = totalWordCounts.add(fileWordCount);
-            stringBuilder.append(fileFormattedString).append('\n');
-        }
-        // add additional total row
-        if (files.size() > 1) {
-            stringBuilder.append(formatWordCounts(totalWordCounts, "total"));
-        }
-
-        String report = stringBuilder.toString();
-        return report;
-    }
-
-    /**
-     * Set the default options for this action if none have been supplied.
-     */
-    protected void setDefaultOptions() {
-        boolean noOptionsSupplied = !(bytes || chars || lines || words);
-
-        if (noOptionsSupplied) {
-            lines = true;
-            words = true;
-            bytes = true;
-        }
-    }
-
-    /**
-     * <p>Perform the main logic of counting the relevant data within a given input stream.</p>
-     * <p>Note, a line is considered to be terminated by linefeed '\n' or carriage return '\r'.</p>
-     * <p>A previous linefeed will be consumed.</p>
-     * <p>This method assumes UTF-8.</p>
-     *
-     * @param inputStream the input stream.
-     * @return the word count result.
-     * @throws IOException in case of word count failure.
-     */
-    protected WordCounts getWordCounts(InputStream inputStream) throws IOException {
-        WordCounts wordCounts = new WordCounts();
-
-        BufferedReader bufferedReader = null;
-        try {
-            bufferedReader = new BufferedReader(new InputStreamReader(inputStream));
-
-            int current;
-            boolean skipNextLineFeed = false;
-            boolean previouslyWhitespace = true;
-            while ((current = bufferedReader.read()) != -1) {
-                wordCounts.byteCount++;
-                wordCounts.charCount++;
-
-                // line handling
-                // if the previous read was a new line, skip the next newline feed
-                boolean isSkipNewlineFeed = skipNextLineFeed && current == '\n';
-                skipNextLineFeed = false;
-                if (isSkipNewlineFeed) {
-                    continue;
-                }
-
-                boolean eol = (current == '\n' || current == '\r');
-                if (eol) {
-                    wordCounts.lineCount++;
-                    // store the state to skip the next newline feed if required
-                    if (current == '\r') {
-                        skipNextLineFeed = true;
-                    }
-                }
-
-                // word handling
-                boolean isCurrentWhitespace = Character.isWhitespace(current);
-                if (!isCurrentWhitespace && previouslyWhitespace) {
-                    wordCounts.wordCount++;
-                }
-                previouslyWhitespace = isCurrentWhitespace;
-            }
-        } finally {
-            if (bufferedReader != null) {
-                bufferedReader.close();
-            }
-        }
-
-        return wordCounts;
-    }
-
-    /**
-     * Create a human readable format of the given count information.
-     *
-     * @param wordCounts the word count object containing the information.
-     * @param reportName the name associated with the word counts, ie a file name.
-     * @return a human readable String representing the word count information.
-     */
-    protected String formatWordCounts(WordCounts wordCounts, String reportName) {
-        // line word chars
-        StringBuilder stringBuilder = new StringBuilder();
-
-        if (lines) {
-            stringBuilder.append('\t').append(wordCounts.lineCount);
-        }
-
-        if (words) {
-            stringBuilder.append('\t').append(wordCounts.wordCount);
-        }
-
-        if (chars) {
-            stringBuilder.append('\t').append(wordCounts.charCount);
-        }
-
-        if (bytes) {
-            stringBuilder.append('\t').append(wordCounts.byteCount);
-        }
-
-        if (reportName != null) {
-            stringBuilder.append('\t').append(reportName);
-        }
-
-        String formattedString = stringBuilder.toString();
-
-        return formattedString;
-    }
-
-    /**
-     * Represent a basic object to store the word count data.
-     */
-    protected static class WordCounts {
-
-        protected int lineCount;
-        protected int wordCount;
-        protected int byteCount;
-        protected int charCount;
-
-        public WordCounts add(WordCounts append) {
-            WordCounts wordCounts = new WordCounts();
-            wordCounts.charCount = charCount + append.charCount;
-            wordCounts.byteCount = byteCount + append.byteCount;
-            wordCounts.lineCount = lineCount + append.lineCount;
-            wordCounts.wordCount = wordCount + append.wordCount;
-            return wordCounts;
-        }
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/WhileAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/WhileAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/WhileAction.java
deleted file mode 100644
index 90b17a6..0000000
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/WhileAction.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.util.Collection;
-import java.util.Collections;
-
-import org.apache.karaf.shell.api.action.Action;
-import org.apache.karaf.shell.api.action.Argument;
-import org.apache.karaf.shell.api.action.Command;
-import org.apache.karaf.shell.api.action.lifecycle.Reference;
-import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.shell.api.console.Function;
-import org.apache.karaf.shell.api.console.Session;
-
-/**
- * Execute a closure on a list of arguments.
- */
-@Command(scope = "shell", name = "while", description = "Loop while the condition is true.")
-@Service
-public class WhileAction implements Action {
-
-    @Argument(name = "condition", index = 0, multiValued = false, required = true, description = "The condition of the loop")
-    Function condition;
-
-    @Argument(name = "function", index = 1, multiValued = false, required = true, description = "The function to execute")
-    Function function;
-
-    @Reference
-    Session session;
-
-    @Override
-    public Object execute() throws Exception {
-        while (isTrue(condition.execute(session, null))) {
-            function.execute(session, null);
-            if (Thread.currentThread().isInterrupted()) {
-                throw new InterruptedException();
-            }
-        }
-        return null;
-    }
-
-    private boolean isTrue(Object result) {
-        if (result == null) {
-            return false;
-        }
-        if (result instanceof String && ((String) result).equals("")) {
-            return false;
-        }
-        if (result instanceof Number) {
-            return ((Number) result).doubleValue() != 0.0d;
-        }
-        if (result instanceof Boolean) {
-            return (Boolean) result;
-        }
-        return true;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/resources/META-INF/services/org/apache/karaf/shell/commands b/shell/commands/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
index 686ce64..483823b 100644
--- a/shell/commands/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
+++ b/shell/commands/src/main/resources/META-INF/services/org/apache/karaf/shell/commands
@@ -14,33 +14,14 @@
 ##  See the License for the specific language governing permissions and
 ##  limitations under the License.
 ##---------------------------------------------------------------------------
-org.apache.karaf.shell.commands.impl.AliasAction
-org.apache.karaf.shell.commands.impl.CatAction
-org.apache.karaf.shell.commands.impl.ClearAction
 org.apache.karaf.shell.commands.impl.CompletionAction
-org.apache.karaf.shell.commands.impl.DateAction
-org.apache.karaf.shell.commands.impl.EachAction
-org.apache.karaf.shell.commands.impl.EchoAction
-org.apache.karaf.shell.commands.impl.EditAction
-org.apache.karaf.shell.commands.impl.EnvAction
 org.apache.karaf.shell.commands.impl.ExecuteAction
-org.apache.karaf.shell.commands.impl.GrepAction
-org.apache.karaf.shell.commands.impl.HeadAction
-org.apache.karaf.shell.commands.impl.HistoryAction
-org.apache.karaf.shell.commands.impl.IfAction
 org.apache.karaf.shell.commands.impl.InfoAction
 org.apache.karaf.shell.commands.impl.JavaAction
 org.apache.karaf.shell.commands.impl.LogoutAction
-org.apache.karaf.shell.commands.impl.MoreAction
-org.apache.karaf.shell.commands.impl.NewAction
 org.apache.karaf.shell.commands.impl.PrintfAction
 org.apache.karaf.shell.commands.impl.PrintStackTracesAction
-org.apache.karaf.shell.commands.impl.SleepAction
-org.apache.karaf.shell.commands.impl.SortAction
 org.apache.karaf.shell.commands.impl.SourceAction
-org.apache.karaf.shell.commands.impl.TacAction
-org.apache.karaf.shell.commands.impl.TailAction
 org.apache.karaf.shell.commands.impl.ThreadsAction
 org.apache.karaf.shell.commands.impl.TTopAction
 org.apache.karaf.shell.commands.impl.WatchAction
-org.apache.karaf.shell.commands.impl.WcAction

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/resources/org/apache/karaf/shell/commands/impl/grep.txt
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/resources/org/apache/karaf/shell/commands/impl/grep.txt b/shell/commands/src/main/resources/org/apache/karaf/shell/commands/impl/grep.txt
deleted file mode 100644
index 1ada069..0000000
--- a/shell/commands/src/main/resources/org/apache/karaf/shell/commands/impl/grep.txt
+++ /dev/null
@@ -1 +0,0 @@
-Grep uses Java regular expressions for pattern matching.  For more informations, see http://download.oracle.com/javase/1.5.0/docs/api/java/util/regex/Pattern.html

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/main/resources/org/apache/karaf/shell/commands/impl/wc.txt
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/resources/org/apache/karaf/shell/commands/impl/wc.txt b/shell/commands/src/main/resources/org/apache/karaf/shell/commands/impl/wc.txt
deleted file mode 100644
index 0923c71..0000000
--- a/shell/commands/src/main/resources/org/apache/karaf/shell/commands/impl/wc.txt
+++ /dev/null
@@ -1,35 +0,0 @@
-This command will output the information in the following format
-
-    Lines     Words     Characters     Bytes     Name
-
-Note, the name field will not always be present. For example, in the case of a piped
-application of wc.
-
-Example usage :
-
-    Display information about a single file
-
-        wc LICENSE
-
-    Which outputs
-
-        475     4053    28230   LICENSE
-
-    Display information about multiple files
-
-        wc LICENSE README RELEASE-NOTES
-
-    Which outputs
-
-        475     4053    28230   LICENSE
-        77      562     3933    README
-        1831    16765   118449  RELEASE-NOTES
-        2383    21380   150612  total
-
-    Piped example
-
-        echo "Hello World" | wc -w -l
-
-    Which outputs
-
-        1       2
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java b/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java
deleted file mode 100644
index c2bea94..0000000
--- a/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/GrepTest.java
+++ /dev/null
@@ -1,312 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import org.apache.karaf.shell.impl.action.command.DefaultActionPreparator;
-import org.junit.Test;
-
-import java.io.ByteArrayInputStream;
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Collectors;
-
-import static org.junit.Assert.*;
-
-public class GrepTest {
-
-    private static final String ANSI_COLOR = "\u001b[1;31m";
-    private static final String ANSI_RESET = "\u001b[0m";
-
-    @Test
-    public void testGrep() throws Exception {
-        final String expectedColoredString = "1\n" + ANSI_COLOR + "2"
-            + ANSI_RESET + "\n"
-            + "3\n4\n5\n6\n7\n8\n9";
-
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("--color", "always", "-C", "100", "2"));
-        final String returnedString = systemInOutDecorator("1\n2\n3\n4\n5\n6\n7\n8\n9\n", grep);
-        assertEquals(expectedColoredString, returnedString);
-    }
-
-    @Test
-    public void testGrepInverted() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-v", "--color", "never", "mine"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("This is Hello World\nHello World!", returnedString);
-    }
-
-    @Test
-    public void testGrepMatching() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("--color", "never", "mine"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("World is mine", returnedString);
-    }
-
-    @Test
-    public void testGrepMatchingWithColours() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("--color", "always", "mine"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("World is " + ANSI_COLOR + "mine" + ANSI_RESET, returnedString);
-    }
-
-    @Test
-    public void testGrepCount() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-c", "Hello World"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("2", returnedString);
-    }
-
-    @Test
-    public void testGrepCountInvert() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-c", "-v", "Hello World"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("1", returnedString);
-    }
-
-    @Test
-    public void testGrepInvertedWithLineNumbers() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-n", "-v", "--color", "never", "mine"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("     1  This is Hello World\n     3  Hello World!", returnedString);
-    }
-
-    @Test
-    public void testGrepMatchingWithLineNumbers() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-n", "--color", "never", "Hello"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("     1  This is Hello World\n     3  Hello World!", returnedString);
-    }
-
-    @Test
-    public void testGrepWordRegExp() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-w", "--color", "never", "is"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("This is Hello World\nWorld is mine", returnedString);
-    }
-
-    @Test
-    public void testGrepIs() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("--color", "never", "is"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("This is Hello World\nWorld is mine", returnedString);
-    }
-
-    @Test
-    public void testGrepRegExpWithColour() throws Exception {
-        GrepAction grep = new GrepAction();
-        final String expected = "Th"
-            + ANSI_COLOR
-            + "is" + ANSI_RESET
-            + " "
-            + ANSI_COLOR
-            + "is" + ANSI_RESET
-            + " Hello World\nWorld "
-            + ANSI_COLOR
-            + "is" + ANSI_RESET
-            + " mine";
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("--color", "always", "is"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals(expected, returnedString);
-    }
-
-    @Test
-    public void testGrepWordRegExpWithColour() throws Exception {
-        GrepAction grep = new GrepAction();
-        final String expected = "This "
-            + ANSI_COLOR
-            + "is" + ANSI_RESET
-            + " Hello World\nWorld "
-            + ANSI_COLOR
-            + "is" + ANSI_RESET
-            + " mine";
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-w", "--color", "always", "is"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals(expected, returnedString);
-    }
-
-    @Test
-    public void testGrepLineRegExpWithColour() throws Exception {
-        GrepAction grep = new GrepAction();
-        final String expected = ANSI_COLOR
-            + "This is Hello World" + ANSI_RESET;
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-x", "--color", "always", ".*Hello World"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals(expected, returnedString);
-    }
-
-    @Test
-    public void testGrepTwoLinesRegExpWithColour() throws Exception {
-        GrepAction grep = new GrepAction();
-        final String expected = ANSI_COLOR
-            + "This is Hello World" + ANSI_RESET + "\n"
-            + ANSI_COLOR
-            + "Hello World!" + ANSI_RESET;
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-x", "--color", "always", ".*Hello World.*"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals(expected, returnedString);
-    }
-
-    @Test
-    public void testGrepIgnoreCaseWithColour() throws Exception {
-        GrepAction grep = new GrepAction();
-        final String expected = "This is "
-            + ANSI_COLOR
-            + "hello" + ANSI_RESET + " World\n"
-            + ANSI_COLOR
-            + "Hello" + ANSI_RESET + " World!";
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-i", "--color", "always", "HELLO"));
-        final String returnedString = systemInOutDecorator("This is hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals(expected, returnedString);
-    }
-
-    @Test
-    public void testGrepContextOneWithColour() throws Exception {
-        GrepAction grep = new GrepAction();
-        final String expected = "This is "
-            + ANSI_COLOR
-            + "Hello" + ANSI_RESET + " World\n"
-            + "World is mine\n"
-            + ANSI_COLOR
-            + "Hello" + ANSI_RESET + " World!";
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-C", "1", "--color", "always", "Hello"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals(expected, returnedString);
-    }
-
-    @Test
-    public void testGrepBeforeContextOneWithColour() throws Exception {
-        GrepAction grep = new GrepAction();
-        final String expected = "World is mine\n"
-            + ANSI_COLOR
-            + "Hello World!" + ANSI_RESET;
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-B", "1", "--color", "always", "Hello World!"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals(expected, returnedString);
-    }
-
-    @Test
-    public void testGrepAfterContextOneWithColour() throws Exception {
-        GrepAction grep = new GrepAction();
-        final String expected = "World is "
-            + ANSI_COLOR
-            + "mine" + ANSI_RESET
-            + "\nHello World!";
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-A", "1", "--color", "always", "mine"));
-        final String returnedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals(expected, returnedString);
-    }
-
-    @Test
-    public void testGrepOnlyMatching() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-o", "--color", "never", "He.*rld"));
-        final String expectedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("Hello World\nHello World", expectedString);
-    }
-
-    @Test
-    public void testGrepOnlyMatchingGroup() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("-o", "--color", "never", "(This).*(Hello)"));
-        final String expectedString = systemInOutDecorator("This is Hello World\nWorld is mine\nHello World!\n",
-            grep);
-        assertEquals("This is Hello", expectedString);
-    }
-
-    @Test
-    public void testHonorColorNever() throws Exception {
-        GrepAction grep = new GrepAction();
-        DefaultActionPreparator preparator = new DefaultActionPreparator();
-        preparator.prepare(grep, null, Arrays.asList("--color", "never", "b"));
-        final String expectedString = systemInOutDecorator("abc\n",
-            grep);
-        assertEquals("abc", expectedString);
-
-    }
-
-    private String systemInOutDecorator(String inputString, GrepAction grepExecute) throws Exception {
-        InputStream input = System.in;
-        PrintStream output = System.out;
-        try {
-            ByteArrayInputStream bais = new ByteArrayInputStream(inputString.getBytes());
-            System.setIn(bais);
-
-            String result = ((List<Object>) grepExecute.execute()).stream()
-                    .map(Object::toString).collect(Collectors.joining("\n"));
-            if (result.length() > 1 && result.charAt(result.length() - 1) == '\n') {
-                result = result.substring(0, result.length() - 1);
-            }
-            return result;
-        } finally {
-            System.setIn(input);
-            System.setOut(output);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/SortTest.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/SortTest.java b/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/SortTest.java
deleted file mode 100644
index f2b2f1b..0000000
--- a/shell/commands/src/test/java/org/apache/karaf/shell/commands/impl/SortTest.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.karaf.shell.commands.impl;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.Field;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Collections;
-
-import org.apache.karaf.shell.commands.impl.SortAction;
-
-import junit.framework.TestCase;
-
-public class SortTest extends TestCase {
-
-    public void testFieldIndexesDefaultSep() {
-        SortAction.SortComparator comparator = new SortAction.SortComparator(false, false, false, false, '\0', null);
-        List<Integer> indexes = comparator.getFieldIndexes(" ad  re  t ");
-        assertTrue(Arrays.asList(0, 2, 3, 6, 7, 9, 10, 10).equals(indexes));
-    }
-
-    public void testFieldIndexesWithSep() {
-        SortAction.SortComparator comparator = new SortAction.SortComparator(false, false, false, false, '[', null);
-        List<Integer> indexes = comparator.getFieldIndexes("[  10] [Active     ] [       ] [    8] OPS4J Pax Logging - Service (1.3.0)");
-        assertTrue(Arrays.asList(1, 6, 8, 20, 22, 30, 32, 73 ).equals(indexes));
-
-        indexes = comparator.getFieldIndexes(" ad  re  t ");
-        assertTrue(Arrays.asList(0, 10).equals(indexes));
-    }
-
-    public void testSort() {
-        String s0 = "0321   abcd  ddcba   a";
-        String s1 = " 57t   bcad  ddacb   b";
-        String s2 = "  128  cab   ddbac   c";
-        List<String> strings = Arrays.asList(s0, s1, s2);
-
-        Collections.sort(strings, new SortAction.SortComparator(false, false, false, false, '\0', Arrays.asList("2")));
-        assertTrue(Arrays.asList(s0, s1, s2).equals(strings));
-
-        Collections.sort(strings, new SortAction.SortComparator(false, false, false, false, '\0', Arrays.asList("2.2b")));
-        assertTrue(Arrays.asList(s2, s0, s1).equals(strings));
-
-        Collections.sort(strings, new SortAction.SortComparator(false, false, false, true, '\0', null));
-        assertTrue(Arrays.asList(s1, s2, s0).equals(strings));
-
-        Collections.sort(strings, new SortAction.SortComparator(false, true, false, false, '\0', Arrays.asList("4")));
-        assertTrue(Arrays.asList(s2, s1, s0).equals(strings));
-    }
-
-    public void testSortToStdout() throws Exception {
-        String newLine = System.getProperty("line.separator");
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        byte[] input = ("abc" + newLine + "def" + newLine).getBytes();
-        new SortAction().sort(new ByteArrayInputStream(input), new PrintStream(baos));
-        assertEquals(new String(input), new String(baos.toByteArray()));
-    }
-
-    public void testUniqSortToStdout() throws Exception {
-        String newLine = System.getProperty("line.separator");
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        String inputString = "def" + newLine + "def" + newLine + "abc" + newLine + "abc" + newLine + "def" + newLine;
-        byte[] input = inputString.getBytes();
-        String outputString = ("abc" + newLine + "def" + newLine);
-        SortAction sort = new SortAction();
-        Field unique = SortAction.class.getDeclaredField("unique");
-        unique.setAccessible(true);
-        unique.set(sort, true);
-        sort.sort(new ByteArrayInputStream(input), new PrintStream(baos));
-        assertEquals(outputString, new String(baos.toByteArray()));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/console/pom.xml
----------------------------------------------------------------------
diff --git a/shell/console/pom.xml b/shell/console/pom.xml
index 45804c4..0fc579b 100644
--- a/shell/console/pom.xml
+++ b/shell/console/pom.xml
@@ -175,9 +175,10 @@
                             org.apache.karaf.shell.inject;version=${project.version};-noimport:=true,
                         	org.apache.karaf.shell.util;version=${project.version};-noimport:=true,
                             org.apache.karaf.shell.util;version=2.3.0;-noimport:=true,
-                            org.apache.felix.gogo*;version=${felix.gogo.runtime.version};-noimport:=true,
-                            org.apache.felix.service.command;version=${felix.gogo.runtime.version};-noimport:=true,
-                            org.apache.felix.service.threadio;version=${felix.gogo.runtime.version};status=provisional;mandatory:=status;-noimport:=true
+                            org.apache.felix.gogo.api;version=0.17.0;status=provisional;-noimport:=true,
+                            org.apache.felix.gogo.commands.*;version=0.17.0;-noimport:=true,
+                            org.apache.felix.service.command;version=0.17.0;status=provisional;-noimport:=true,
+                            org.apache.felix.service.threadio;version=0.17.0;status=provisional;-noimport:=true
                         </Export-Package>
                         <Private-Package>
                         	org.apache.karaf.shell.commands.ansi,

http://git-wip-us.apache.org/repos/asf/karaf/blob/f1dd4a94/shell/console/src/main/java/org/apache/karaf/shell/compat/CommandTracker.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/compat/CommandTracker.java b/shell/console/src/main/java/org/apache/karaf/shell/compat/CommandTracker.java
index 8891135..e079ab9 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/compat/CommandTracker.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/compat/CommandTracker.java
@@ -19,13 +19,10 @@
 package org.apache.karaf.shell.compat;
 
 import java.lang.reflect.Method;
-import java.util.ArrayList;
 import java.util.List;
 
-import org.apache.felix.gogo.runtime.CommandProxy;
 import org.apache.felix.service.command.CommandProcessor;
 import org.apache.felix.service.command.CommandSession;
-import org.apache.felix.service.command.Function;
 import org.apache.karaf.shell.api.console.CommandLine;
 import org.apache.karaf.shell.api.console.Completer;
 import org.apache.karaf.shell.api.console.Parser;
@@ -34,6 +31,7 @@ import org.apache.karaf.shell.api.console.SessionFactory;
 import org.apache.karaf.shell.commands.Command;
 import org.apache.karaf.shell.commands.CommandWithAction;
 import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
 import org.osgi.framework.Filter;
 import org.osgi.framework.ServiceReference;
 import org.osgi.util.tracker.ServiceTracker;
@@ -53,8 +51,10 @@ public class CommandTracker implements ServiceTrackerCustomizer<Object, Object>
     }
 
     public void init() throws Exception {
-        Filter filter = context.createFilter(String.format("(&(%s=*)(%s=*))",
-                CommandProcessor.COMMAND_SCOPE, CommandProcessor.COMMAND_FUNCTION));
+        Filter filter = context.createFilter(String.format("(&(%s=*)(%s=*)(|(%s=%s)(%s=%s)))",
+                CommandProcessor.COMMAND_SCOPE, CommandProcessor.COMMAND_FUNCTION,
+                Constants.OBJECTCLASS, CommandWithAction.class.getName(),
+                Constants.OBJECTCLASS, org.apache.felix.gogo.commands.CommandWithAction.class.getName()));
         this.tracker = new ServiceTracker<Object, Object>(context, filter, this);
         this.tracker.open();
     }
@@ -178,96 +178,7 @@ public class CommandTracker implements ServiceTrackerCustomizer<Object, Object>
             sessionFactory.getRegistry().register(command);
             return command;
         } else {
-            final String scope = reference.getProperty(CommandProcessor.COMMAND_SCOPE).toString();
-            final Object function = reference.getProperty(CommandProcessor.COMMAND_FUNCTION);
-
-            List<org.apache.karaf.shell.api.console.Command> commands = new ArrayList<>();
-
-            if (function.getClass().isArray()) {
-                for (final Object f : ((Object[]) function)) {
-                    final Function target;
-
-                    target = new CommandProxy(context, reference, f.toString());
-                    org.apache.karaf.shell.api.console.Command command = new org.apache.karaf.shell.api.console.Command() {
-                        @Override
-                        public String getScope() {
-                            return scope;
-                        }
-
-                        @Override
-                        public String getName() {
-                            return f.toString();
-                        }
-
-                        @Override
-                        public String getDescription() {
-                            Object property = reference.getProperty("osgi.command.description");
-                            if (property != null) {
-                                return property.toString();
-                            } else {
-                                return getName();
-                            }
-                        }
-
-                        @Override
-                        public Completer getCompleter(final boolean scoped) {
-                            return null;
-                        }
-
-                        @Override
-                        public Parser getParser() {
-                            return null;
-                        }
-
-                        @Override
-                        public Object execute(Session session, List<Object> arguments) throws Exception {
-                            // TODO: remove not really nice cast
-                            CommandSession commandSession = (CommandSession) session.get(".commandSession");
-                            return target.execute(commandSession, arguments);
-                        }
-                    };
-                    sessionFactory.getRegistry().register(command);
-                    commands.add(command);
-                }
-            } else {
-                final Function target = new CommandProxy(context, reference, function.toString());
-                org.apache.karaf.shell.api.console.Command command = new org.apache.karaf.shell.api.console.Command() {
-                    @Override
-                    public String getScope() {
-                        return scope;
-                    }
-
-                    @Override
-                    public String getName() {
-                        return function.toString();
-                    }
-
-                    @Override
-                    public String getDescription() {
-                        return reference.getProperty("osgi.command.description").toString();
-                    }
-
-                    @Override
-                    public Completer getCompleter(final boolean scoped) {
-                        return null;
-                    }
-
-                    @Override
-                    public Parser getParser() {
-                        return null;
-                    }
-
-                    @Override
-                    public Object execute(Session session, List<Object> arguments) throws Exception {
-                        // TODO: remove not really nice cast
-                        CommandSession commandSession = (CommandSession) session.get(".commandSession");
-                        return target.execute(commandSession, arguments);
-                    }
-                };
-                sessionFactory.getRegistry().register(command);
-                commands.add(command);
-            }
-            return commands;
+            return null;
         }
     }