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/06/14 13:23:16 UTC

[1/6] karaf git commit: Use a BiConsumer in SingleServiceTracker instead of a custom interface

Repository: karaf
Updated Branches:
  refs/heads/master 64093884c -> b4ae5245c


Use a BiConsumer in SingleServiceTracker instead of a custom interface

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

Branch: refs/heads/master
Commit: d4002bac4bbbd0359193cc6d47423db54cfaea15
Parents: 6409388
Author: Guillaume Nodet <gn...@apache.org>
Authored: Thu Jun 2 15:15:47 2016 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Jun 14 14:15:47 2016 +0200

----------------------------------------------------------------------
 .../karaf/diagnostic/internal/Activator.java    | 24 ++++++-------
 .../osgi/secured/SecuredSessionFactoryImpl.java | 17 ++-------
 .../karaf/util/tracker/BaseActivator.java       | 23 +++---------
 .../util/tracker/SingleServiceTracker.java      | 38 +++++++-------------
 4 files changed, 30 insertions(+), 72 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/d4002bac/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/internal/Activator.java
----------------------------------------------------------------------
diff --git a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/internal/Activator.java b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/internal/Activator.java
index 42f1c4b..e227d27 100644
--- a/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/internal/Activator.java
+++ b/diagnostic/core/src/main/java/org/apache/karaf/diagnostic/internal/Activator.java
@@ -25,6 +25,7 @@ import org.apache.karaf.diagnostic.management.internal.DiagnosticDumpMBeanImpl;
 import org.apache.karaf.diagnostic.common.FeaturesDumpProvider;
 import org.apache.karaf.diagnostic.common.LogDumpProvider;
 import org.apache.karaf.features.FeaturesService;
+import org.apache.karaf.features.internal.model.Features;
 import org.apache.karaf.util.tracker.SingleServiceTracker;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
@@ -44,21 +45,16 @@ public class Activator implements BundleActivator {
         registrations = new ArrayList<ServiceRegistration<DumpProvider>>();
         registrations.add(context.registerService(DumpProvider.class, new LogDumpProvider(context), null));
 
-        featuresServiceTracker = new SingleServiceTracker<FeaturesService>(context, FeaturesService.class, new SingleServiceTracker.SingleServiceListener() {
-            @Override
-            public void serviceFound() {
-                featuresProviderRegistration =
-                        context.registerService(
-                                DumpProvider.class,
-                                new FeaturesDumpProvider(featuresServiceTracker.getService()),
-                                null);
-            }
-            @Override
-            public void serviceLost() {
-            }
-            @Override
-            public void serviceReplaced() {
+        featuresServiceTracker = new SingleServiceTracker<FeaturesService>(context, FeaturesService.class, (oldFs, newFs) -> {
+            if (featuresProviderRegistration != null) {
                 featuresProviderRegistration.unregister();
+                featuresProviderRegistration = null;
+            }
+            if (newFs != null) {
+                featuresProviderRegistration = context.registerService(
+                        DumpProvider.class,
+                        new FeaturesDumpProvider(newFs),
+                        null);
             }
         });
         featuresServiceTracker.open();

http://git-wip-us.apache.org/repos/asf/karaf/blob/d4002bac/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
index 1f2c4da..ef85ce2 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/secured/SecuredSessionFactoryImpl.java
@@ -49,7 +49,7 @@ import org.osgi.service.cm.ConfigurationListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements ConfigurationListener, SingleServiceTracker.SingleServiceListener {
+public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements ConfigurationListener {
 
     private static final String PROXY_COMMAND_ACL_PID_PREFIX = "org.apache.karaf.command.acl.";
     private static final String CONFIGURATION_FILTER =
@@ -66,7 +66,7 @@ public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements Con
         super(threadIO);
         this.bundleContext = bundleContext;
         this.registration = bundleContext.registerService(ConfigurationListener.class, this, null);
-        this.configAdminTracker = new SingleServiceTracker<>(bundleContext, ConfigurationAdmin.class, this);
+        this.configAdminTracker = new SingleServiceTracker<>(bundleContext, ConfigurationAdmin.class, this::update);
         this.configAdminTracker.open();
     }
 
@@ -212,10 +212,8 @@ public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements Con
         }
     }
 
-    @Override
-    public void serviceFound() {
+    protected void update(ConfigurationAdmin prev, ConfigurationAdmin configAdmin) {
         try {
-            ConfigurationAdmin configAdmin = this.configAdminTracker.getService();
             Configuration[] configs = configAdmin.listConfigurations(CONFIGURATION_FILTER);
             if (configs != null) {
                 for (Configuration config : configs) {
@@ -226,13 +224,4 @@ public class SecuredSessionFactoryImpl extends SessionFactoryImpl implements Con
             // Ignore, should never happen
         }
     }
-
-    @Override
-    public void serviceLost() {
-    }
-
-    @Override
-    public void serviceReplaced() {
-        serviceFound();
-    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/d4002bac/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java b/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
index a1e8a6d..53c0c23 100644
--- a/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
+++ b/util/src/main/java/org/apache/karaf/util/tracker/BaseActivator.java
@@ -39,7 +39,7 @@ import org.osgi.framework.ServiceRegistration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-public class BaseActivator implements BundleActivator, SingleServiceTracker.SingleServiceListener, Runnable {
+public class BaseActivator implements BundleActivator, Runnable {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
     protected BundleContext bundleContext;
@@ -223,21 +223,6 @@ public class BaseActivator implements BundleActivator, SingleServiceTracker.Sing
         return def;
     }
 
-    @Override
-    public void serviceFound() {
-        reconfigure();
-    }
-
-    @Override
-    public void serviceLost() {
-        reconfigure();
-    }
-
-    @Override
-    public void serviceReplaced() {
-        reconfigure();
-    }
-
     protected void reconfigure() {
         if (scheduled.compareAndSet(false, true)) {
             executor.submit(this);
@@ -264,7 +249,7 @@ public class BaseActivator implements BundleActivator, SingleServiceTracker.Sing
      */
     protected void trackService(Class<?> clazz) throws InvalidSyntaxException {
         if (!trackers.containsKey(clazz.getName())) {
-            SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, clazz, this);
+            SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, clazz, (u, v) -> reconfigure());
             tracker.open();
             trackers.put(clazz.getName(), tracker);
         }
@@ -282,7 +267,7 @@ public class BaseActivator implements BundleActivator, SingleServiceTracker.Sing
             if (filter != null && filter.isEmpty()) {
                 filter = null;
             }
-            SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, clazz, filter, this);
+            SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, clazz, filter, (u, v) -> reconfigure());
             tracker.open();
             trackers.put(clazz.getName(), tracker);
         }
@@ -290,7 +275,7 @@ public class BaseActivator implements BundleActivator, SingleServiceTracker.Sing
 
     protected void trackService(String className, String filter) throws InvalidSyntaxException {
         if (!trackers.containsKey(className)) {
-            SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, className, filter, this);
+            SingleServiceTracker tracker = new SingleServiceTracker<>(bundleContext, className, filter, (u, v) -> reconfigure());
             tracker.open();
             trackers.put(className, tracker);
         }

http://git-wip-us.apache.org/repos/asf/karaf/blob/d4002bac/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java b/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
index d46d829..0c52575 100644
--- a/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
+++ b/util/src/main/java/org/apache/karaf/util/tracker/SingleServiceTracker.java
@@ -21,6 +21,7 @@ package org.apache.karaf.util.tracker;
 import java.util.Arrays;
 import java.util.concurrent.atomic.AtomicBoolean;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiConsumer;
 
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
@@ -33,32 +34,24 @@ import org.osgi.framework.ServiceReference;
 //This is from aries util
 public final class SingleServiceTracker<T> implements ServiceListener {
 
-    public static interface SingleServiceListener {
-        public void serviceFound();
-
-        public void serviceLost();
-
-        public void serviceReplaced();
-    }
-
     private final BundleContext ctx;
     private final String className;
     private final AtomicReference<T> service = new AtomicReference<>();
     private final AtomicReference<ServiceReference> ref = new AtomicReference<>();
     private final AtomicBoolean open = new AtomicBoolean(false);
-    private final SingleServiceListener serviceListener;
+    private final BiConsumer<T, T> serviceListener;
     private final String filterString;
     private final Filter filter;
 
-    public SingleServiceTracker(BundleContext context, Class<T> clazz, SingleServiceListener sl) throws InvalidSyntaxException {
+    public SingleServiceTracker(BundleContext context, Class<T> clazz, BiConsumer<T, T> sl) throws InvalidSyntaxException {
         this(context, clazz, null, sl);
     }
 
-    public SingleServiceTracker(BundleContext context, Class<T> clazz, String filterString, SingleServiceListener sl) throws InvalidSyntaxException {
+    public SingleServiceTracker(BundleContext context, Class<T> clazz, String filterString, BiConsumer<T, T> sl) throws InvalidSyntaxException {
         this(context, clazz.getName(), filterString, sl);
     }
 
-    public SingleServiceTracker(BundleContext context, String className, String filterString, SingleServiceListener sl) throws InvalidSyntaxException {
+    public SingleServiceTracker(BundleContext context, String className, String filterString, BiConsumer<T, T> sl) throws InvalidSyntaxException {
         this.ctx = context;
         this.className = className;
         this.serviceListener = sl;
@@ -119,7 +112,7 @@ public final class SingleServiceTracker<T> implements ServiceListener {
                     clear = false;
 
                     // We do the unget out of the lock so we don't exit this class while holding a lock.
-                    if (!!!update(original, refs[0], service)) {
+                    if (!update(original, refs[0], service)) {
                         ctx.ungetService(refs[0]);
                     }
                 }
@@ -137,7 +130,7 @@ public final class SingleServiceTracker<T> implements ServiceListener {
 
     private boolean update(ServiceReference deadRef, ServiceReference newRef, T service) {
         boolean result = false;
-        int foundLostReplaced = -1;
+        T prev = null;
 
         // Make sure we don't try to get a lock on null
         Object lock;
@@ -153,19 +146,13 @@ public final class SingleServiceTracker<T> implements ServiceListener {
             if (open.get()) {
                 result = this.ref.compareAndSet(deadRef, newRef);
                 if (result) {
-                    this.service.set(service);
-
-                    if (deadRef == null && newRef != null) foundLostReplaced = 0;
-                    if (deadRef != null && newRef == null) foundLostReplaced = 1;
-                    if (deadRef != null && newRef != null) foundLostReplaced = 2;
+                    prev = this.service.getAndSet(service);
                 }
             }
         }
 
-        if (serviceListener != null) {
-            if (foundLostReplaced == 0) serviceListener.serviceFound();
-            else if (foundLostReplaced == 1) serviceListener.serviceLost();
-            else if (foundLostReplaced == 2) serviceListener.serviceReplaced();
+        if (result && serviceListener != null) {
+            serviceListener.accept(prev, service);
         }
 
         return result;
@@ -176,12 +163,13 @@ public final class SingleServiceTracker<T> implements ServiceListener {
             ctx.removeServiceListener(this);
 
             ServiceReference deadRef;
+            T prev;
             synchronized (this) {
                 deadRef = ref.getAndSet(null);
-                service.set(null);
+                prev = service.getAndSet(null);
             }
             if (deadRef != null) {
-                serviceListener.serviceLost();
+                serviceListener.accept(prev, null);
                 ctx.ungetService(deadRef);
             }
         }


[2/6] karaf git commit: [KARAF-4570] Upgrade to JLine 3

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/standalone/Main.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/standalone/Main.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/standalone/Main.java
index dd9ed00..03290e0 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/standalone/Main.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/standalone/Main.java
@@ -44,10 +44,9 @@ import org.apache.karaf.shell.api.console.Terminal;
 import org.apache.karaf.shell.impl.action.command.ManagerImpl;
 import org.apache.karaf.shell.impl.console.JLineTerminal;
 import org.apache.karaf.shell.impl.console.SessionFactoryImpl;
-import org.apache.karaf.shell.impl.console.TerminalFactory;
 import org.apache.karaf.shell.support.NameScoping;
 import org.apache.karaf.shell.support.ShellUtil;
-import org.fusesource.jansi.AnsiConsole;
+import org.jline.terminal.TerminalBuilder;
 
 public class Main {
 
@@ -67,12 +66,13 @@ public class Main {
      */
     public void run(String args[]) throws Exception {
 
+        InputStream in = System.in;
+        PrintStream out = System.out;
+        PrintStream err = System.err;
+
         ThreadIOImpl threadio = new ThreadIOImpl();
         threadio.start();
 
-        InputStream in = unwrap(System.in);
-        PrintStream out = wrap(unwrap(System.out));
-        PrintStream err = wrap(unwrap(System.err));
         run(threadio, args, in, out, err);
 
         // TODO: do we need to stop the threadio that was started?
@@ -138,10 +138,8 @@ public class Main {
 
     private void run(final SessionFactory sessionFactory, String command, final InputStream in, final PrintStream out, final PrintStream err, ClassLoader cl) throws Exception {
 
-        final TerminalFactory terminalFactory = new TerminalFactory();
-        try {
-            String term = System.getenv("TERM");
-            final Terminal terminal = new JLineTerminal(terminalFactory.getTerminal(), term);
+        try (org.jline.terminal.Terminal jlineTerminal = TerminalBuilder.terminal()) {
+            final Terminal terminal = new JLineTerminal(jlineTerminal);
             Session session = createSession(sessionFactory, command.length() > 0 ? null : in, out, err, terminal);
             session.put("USER", user);
             session.put("APPLICATION", application);
@@ -163,8 +161,6 @@ public class Main {
                 // We are going into full blown interactive shell mode.
                 session.run();
             }
-        } finally {
-            terminalFactory.destroy();
         }
     }
 
@@ -246,24 +242,6 @@ public class Main {
         return true;
     }
 
-    private static PrintStream wrap(PrintStream stream) {
-        OutputStream o = AnsiConsole.wrapOutputStream(stream);
-        if (o instanceof PrintStream) {
-            return ((PrintStream) o);
-        } else {
-            return new PrintStream(o);
-        }
-    }
-
-    private static <T> T unwrap(T stream) {
-        try {
-            Method mth = stream.getClass().getMethod("getRoot");
-            return (T) mth.invoke(stream);
-        } catch (Throwable t) {
-            return stream;
-        }
-    }
-
     private static List<URL> getFiles(File base) throws MalformedURLException {
         List<URL> urls = new ArrayList<URL>();
         getFiles(base, urls);

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/AnsiSplitter.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/AnsiSplitter.java b/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/AnsiSplitter.java
index d729cfc..b54ecf1 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/AnsiSplitter.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/AnsiSplitter.java
@@ -18,39 +18,42 @@
  */
 package org.apache.karaf.shell.support.ansi;
 
-import java.io.ByteArrayOutputStream;
+import java.io.BufferedReader;
 import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.util.ArrayList;
 import java.util.List;
+import java.util.stream.Collectors;
 
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.AnsiOutputStream;
+import org.jline.utils.AttributedString;
+import org.jline.utils.AttributedStringBuilder;
 
 public class AnsiSplitter {
 
     public static List<String> splitLines(String text, int maxLength, int tabs) throws IOException {
-        AnsiOutputStreamSplitter splitter = new AnsiOutputStreamSplitter(maxLength);
-        splitter.setTabs(tabs);
-        splitter.write(text.getBytes());
-        splitter.close();
-        return splitter.lines;
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        sb.tabs(tabs);
+        sb.appendAnsi(text);
+        return sb.columnSplitLength(maxLength)
+                .stream()
+                .map(AttributedString::toAnsi)
+                .collect(Collectors.toList());
     }
 
     public static String substring(String text, int begin, int end, int tabs) throws IOException {
-        AnsiOutputStreamSplitter splitter = new AnsiOutputStreamSplitter(begin, end, Integer.MAX_VALUE);
-        splitter.setTabs(tabs);
-        splitter.write(text.getBytes());
-        splitter.close();
-        return splitter.lines.get(0);
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        sb.tabs(tabs);
+        sb.appendAnsi(text);
+        return sb.columnSubSequence(begin, end).toAnsi();
     }
 
-    public static int length(String curLine, int tabs) throws IOException {
-        AnsiOutputStreamSplitter splitter = new AnsiOutputStreamSplitter(0, Integer.MAX_VALUE, Integer.MAX_VALUE);
-        splitter.setTabs(tabs);
-        splitter.write(curLine.getBytes());
-        return splitter.getRealLength();
+    public static int length(String text, int tabs) throws IOException {
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        sb.tabs(tabs);
+        sb.appendAnsi(text);
+        return sb.columnLength();
     }
 
     public static String cut(String text, int maxLength, int tabs)  throws IOException {
@@ -72,29 +75,44 @@ public class AnsiSplitter {
 
     public static class AnsiBufferedReader implements Closeable {
 
-        private final InputStream in;
-        private final AnsiOutputStreamSplitter splitter;
+        private final BufferedReader reader;
+        private final int begin;
+        private final int end;
+        private final int maxLength;
+        private final AttributedStringBuilder builder;
+        private final List<String> lines;
 
         public AnsiBufferedReader(InputStream in, int begin, int end, int maxLength) {
-            this.in = in;
-            this.splitter = new AnsiOutputStreamSplitter(begin, end, maxLength);
+            this.reader = new BufferedReader(new InputStreamReader(in));
+            this.begin = begin;
+            this.end = end;
+            this.maxLength = maxLength;
+            this.builder = new AttributedStringBuilder();
+            this.lines = new ArrayList<>();
         }
 
         public String readLine() throws IOException {
-            while (splitter.lines.isEmpty()) {
-                int c = in.read();
-                if (c < 0) {
-                    splitter.flushLine(false);
-                    break;
+            if (lines.isEmpty()) {
+                String line = reader.readLine();
+                if (line == null) {
+                    return null;
+                }
+                if (line.isEmpty()) {
+                    lines.add("");
                 } else {
-                    splitter.write(c);
+                    builder.setLength(0);
+                    builder.appendAnsi(line);
+                    if (builder.length() > 0) {
+                        builder.style(builder.styleAt(builder.length() - 1));
+                    }
+                    AttributedString str = builder.columnSubSequence(begin, end);
+                    str.columnSplitLength(maxLength)
+                            .stream()
+                            .map(AttributedString::toAnsi)
+                            .forEach(lines::add);
                 }
             }
-            if (splitter.lines.isEmpty()) {
-                return null;
-            } else {
-                return splitter.lines.remove(0);
-            }
+            return lines.remove(0);
         }
 
         @Override
@@ -102,304 +120,8 @@ public class AnsiSplitter {
         }
 
         public void setTabs(int tabs) {
-            this.splitter.setTabs(tabs);
+            this.builder.tabs(tabs);
         }
     }
 
-    static class AnsiOutputStreamSplitter extends AnsiOutputStream {
-
-        protected static final int ATTRIBUTE_NEGATIVE_OFF = 27;
-
-        Ansi.Attribute intensity;
-        Ansi.Attribute underline;
-        Ansi.Attribute blink;
-        Ansi.Attribute negative;
-        Ansi.Color fg;
-        Ansi.Color bg;
-
-        private int begin;
-        private int length;
-        private int maxLength;
-        private int escapeLength;
-        private int windowState;
-        private int tabs;
-        private List<String> lines = new ArrayList<>();
-
-        public AnsiOutputStreamSplitter(int maxLength) {
-            this(0, Integer.MAX_VALUE, maxLength);
-        }
-
-        public AnsiOutputStreamSplitter(int begin, int end, int maxLength) {
-            super(new ByteArrayOutputStream());
-            this.begin = begin;
-            this.length = end - begin;
-            this.maxLength = maxLength - begin;
-            this.windowState = begin > 0 ? 0 : 1;
-            reset();
-        }
-
-        public int getTabs() {
-            return tabs;
-        }
-
-        public void setTabs(int tabs) {
-            this.tabs = tabs;
-        }
-
-        protected void reset() {
-            intensity = Ansi.Attribute.INTENSITY_BOLD_OFF;
-            underline = Ansi.Attribute.UNDERLINE_OFF;
-            blink = Ansi.Attribute.BLINK_OFF;
-            negative = Ansi.Attribute.NEGATIVE_OFF;
-            fg = Ansi.Color.DEFAULT;
-            bg = Ansi.Color.DEFAULT;
-        }
-
-        public int getRealLength() {
-            return ((ByteArrayOutputStream) out).size() - escapeLength;
-        }
-
-        @Override
-        public void write(int data) throws IOException {
-            if (data == '\n') {
-                flushLine(true);
-            } else if (data == '\t') {
-                ByteArrayOutputStream baos = (ByteArrayOutputStream) out;
-                do {
-                    write(' ');
-                } while ((baos.size() - escapeLength) % tabs > 0);
-            } else {
-                if (windowState != 2) {
-                    super.write(data);
-                }
-                ByteArrayOutputStream baos = (ByteArrayOutputStream) out;
-                if (windowState == 0 && baos.size() - escapeLength > begin) {
-                    windowState = 1;
-                    int nbMissing = baos.size() - escapeLength - begin;
-                    byte[] old = baos.toByteArray();
-                    beginAttributes();
-                    baos.write(old, old.length - nbMissing, nbMissing);
-                } else if (windowState == 1 && baos.size() - escapeLength >= length) {
-                    windowState = 2;
-                    endAttributes();
-                    reset();
-                }
-                if (baos.size() - escapeLength >= maxLength) {
-                    flushLine(true);
-                }
-            }
-        }
-
-        @Override
-        public void close() throws IOException {
-            if (windowState == 0) {
-                beginAttributes();
-            }
-            flushLine(lines.isEmpty());
-            super.close();
-        }
-
-        private void flushLine(boolean force) throws IOException {
-            ByteArrayOutputStream baos = (ByteArrayOutputStream) out;
-            if (windowState == 0) {
-                beginAttributes();
-            }
-            if (force || baos.size() > escapeLength) {
-                endAttributes();
-                lines.add(new String(baos.toByteArray()));
-                beginAttributes();
-            }
-            windowState = 0;
-        }
-
-        private void endAttributes() throws IOException {
-            if (intensity != Ansi.Attribute.INTENSITY_BOLD_OFF) {
-                setAttribute(Ansi.Attribute.INTENSITY_BOLD_OFF);
-            }
-            if (underline != Ansi.Attribute.UNDERLINE_OFF) {
-                setAttribute(Ansi.Attribute.UNDERLINE_OFF);
-            }
-            if (blink != Ansi.Attribute.BLINK_OFF) {
-                setAttribute(Ansi.Attribute.BLINK_OFF);
-            }
-            if (negative != Ansi.Attribute.NEGATIVE_OFF) {
-                setAttribute(Ansi.Attribute.NEGATIVE_OFF);
-            }
-            if (fg != Ansi.Color.DEFAULT) {
-                setAttributeFg(Ansi.Color.DEFAULT);
-            }
-            if (bg != Ansi.Color.DEFAULT) {
-                setAttributeBg(Ansi.Color.DEFAULT);
-            }
-        }
-
-        private void beginAttributes() throws IOException {
-            ((ByteArrayOutputStream) out).reset();
-            escapeLength = 0;
-            if (intensity != Ansi.Attribute.INTENSITY_BOLD_OFF) {
-                setAttribute(intensity);
-            }
-            if (underline != Ansi.Attribute.UNDERLINE_OFF) {
-                setAttribute(underline);
-            }
-            if (blink != Ansi.Attribute.BLINK_OFF) {
-                setAttribute(blink);
-            }
-            if (negative != Ansi.Attribute.NEGATIVE_OFF) {
-                setAttribute(negative);
-            }
-            if (fg != Ansi.Color.DEFAULT) {
-                setAttributeFg(fg);
-            }
-            if (bg != Ansi.Color.DEFAULT) {
-                setAttributeBg(bg);
-            }
-        }
-
-        @Override
-        protected void processAttributeRest() throws IOException {
-            setAttribute(Ansi.Attribute.RESET);
-            reset();
-        }
-
-        @Override
-        protected void processSetAttribute(int attribute) throws IOException {
-            switch(attribute) {
-            case ATTRIBUTE_INTENSITY_BOLD:
-                setIntensity(Ansi.Attribute.INTENSITY_BOLD);
-                break;
-            case ATTRIBUTE_INTENSITY_FAINT:
-                setIntensity(Ansi.Attribute.INTENSITY_FAINT);
-                break;
-            case ATTRIBUTE_INTENSITY_NORMAL:
-                setIntensity(Ansi.Attribute.INTENSITY_BOLD_OFF);
-                break;
-            case ATTRIBUTE_UNDERLINE:
-                setUnderline(Ansi.Attribute.UNDERLINE);
-                break;
-            case ATTRIBUTE_UNDERLINE_DOUBLE:
-                setUnderline(Ansi.Attribute.UNDERLINE_DOUBLE);
-                break;
-            case ATTRIBUTE_UNDERLINE_OFF:
-                setUnderline(Ansi.Attribute.UNDERLINE_OFF);
-                break;
-            case ATTRIBUTE_BLINK_OFF:
-                setBlink(Ansi.Attribute.BLINK_OFF);
-                break;
-            case ATTRIBUTE_BLINK_SLOW:
-                setBlink(Ansi.Attribute.BLINK_SLOW);
-                break;
-            case ATTRIBUTE_BLINK_FAST:
-                setBlink(Ansi.Attribute.BLINK_FAST);
-                break;
-            case ATTRIBUTE_NEGATIVE_ON:
-                setNegative(Ansi.Attribute.NEGATIVE_ON);
-                break;
-            case ATTRIBUTE_NEGATIVE_OFF:
-                setNegative(Ansi.Attribute.NEGATIVE_OFF);
-                break;
-            default:
-                break;
-            }
-        }
-
-        @Override
-        protected void processSetForegroundColor(int color) throws IOException {
-            Ansi.Color c;
-            switch (color) {
-            case 0: c = Ansi.Color.BLACK; break;
-            case 1: c = Ansi.Color.RED; break;
-            case 2: c = Ansi.Color.GREEN; break;
-            case 3: c = Ansi.Color.YELLOW; break;
-            case 4: c = Ansi.Color.BLUE; break;
-            case 5: c = Ansi.Color.MAGENTA; break;
-            case 6: c = Ansi.Color.CYAN; break;
-            case 7: c = Ansi.Color.WHITE; break;
-            case 9: c = Ansi.Color.DEFAULT; break;
-            default: return;
-            }
-            if (this.fg != c) {
-                this.fg = c;
-                setAttributeFg(c);
-            }
-        }
-
-        @Override
-        protected void processSetBackgroundColor(int color) throws IOException {
-            Ansi.Color c;
-            switch (color) {
-            case 0: c = Ansi.Color.BLACK; break;
-            case 1: c = Ansi.Color.RED; break;
-            case 2: c = Ansi.Color.GREEN; break;
-            case 3: c = Ansi.Color.YELLOW; break;
-            case 4: c = Ansi.Color.BLUE; break;
-            case 5: c = Ansi.Color.MAGENTA; break;
-            case 6: c = Ansi.Color.CYAN; break;
-            case 7: c = Ansi.Color.WHITE; break;
-            case 9: c = Ansi.Color.DEFAULT; break;
-            default: return;
-            }
-            if (this.bg != c) {
-                this.bg = c;
-                setAttributeBg(c);
-            }
-        }
-
-        @Override
-        protected void processDefaultTextColor() throws IOException {
-            processSetForegroundColor(9);
-        }
-
-        @Override
-        protected void processDefaultBackgroundColor() throws IOException {
-            processSetBackgroundColor(9);
-        }
-
-        protected void setIntensity(Ansi.Attribute intensity) throws IOException {
-            if (this.intensity != intensity) {
-                this.intensity = intensity;
-                setAttribute(intensity);
-            }
-        }
-
-        protected void setUnderline(Ansi.Attribute underline) throws IOException {
-            if (this.underline != underline) {
-                this.underline = underline;
-                setAttribute(underline);
-            }
-        }
-
-        protected void setBlink(Ansi.Attribute blink) throws IOException {
-            if (this.blink != blink) {
-                this.blink = blink;
-                setAttribute(blink);
-            }
-        }
-
-        protected void setNegative(Ansi.Attribute negative) throws IOException {
-            if (this.negative != negative) {
-                this.negative = negative;
-                setAttribute(negative);
-            }
-        }
-
-        private void setAttributeFg(Ansi.Color color) throws IOException {
-            String sequence = Ansi.ansi().fg(color).toString();
-            escapeLength += sequence.length();
-            out.write(sequence.getBytes());
-        }
-
-        private void setAttributeBg(Ansi.Color color) throws IOException {
-            String sequence = Ansi.ansi().bg(color).toString();
-            escapeLength += sequence.length();
-            out.write(sequence.getBytes());
-        }
-
-        private void setAttribute(Ansi.Attribute attribute) throws IOException {
-            String sequence = Ansi.ansi().a(attribute).toString();
-            escapeLength += sequence.length();
-            out.write(sequence.getBytes());
-        }
-
-    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java b/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java
index 92ce8b6..a0b2566 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/ansi/SimpleAnsi.java
@@ -18,14 +18,14 @@
  */
 package org.apache.karaf.shell.support.ansi;
 
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.Ansi.Color;
-
 public class SimpleAnsi {
-    public static String COLOR_RED = Ansi.ansi().fg(Color.RED).toString();
-    public static String COLOR_CYAN = Ansi.ansi().fg(Color.CYAN).toString();
-    public static String COLOR_DEFAULT = Ansi.ansi().fg(Color.DEFAULT).toString();
+    public static String COLOR_RED = "\u001b[31m";
+    public static String COLOR_CYAN = "\u001b[36m";
+    public static String COLOR_YELLOW = "\u001b[33m";
+    public static String COLOR_DEFAULT = "\u001b[39m";
     
-    public static String INTENSITY_BOLD = Ansi.ansi().bold().toString();
-    public static String INTENSITY_NORMAL = Ansi.ansi().boldOff().toString();
+    public static String INTENSITY_BOLD = "\u001b[1m";
+    public static String INTENSITY_NORMAL = "\u001b[22m";
+
+    public static String RESET = "\u001b[m";
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/support/completers/AggregateCompleter.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/completers/AggregateCompleter.java b/shell/core/src/main/java/org/apache/karaf/shell/support/completers/AggregateCompleter.java
index 580f4d2..3a0b58c 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/completers/AggregateCompleter.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/completers/AggregateCompleter.java
@@ -21,9 +21,9 @@ package org.apache.karaf.shell.support.completers;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.LinkedList;
 import java.util.List;
 
+import org.apache.karaf.shell.api.console.Candidate;
 import org.apache.karaf.shell.api.console.CommandLine;
 import org.apache.karaf.shell.api.console.Completer;
 import org.apache.karaf.shell.api.console.Session;
@@ -42,55 +42,22 @@ public class AggregateCompleter implements Completer
     }
 
     @SuppressWarnings({ "unchecked", "rawtypes" })
-    public int complete(final Session session, final CommandLine commandLine, final List candidates) {
+    public int complete(final Session session, final CommandLine commandLine, final List<String> candidates) {
+        List<Candidate> cands = new ArrayList<>();
+        completeCandidates(session, commandLine, cands);
+        for (Candidate cand : cands) {
+            candidates.add(cand.value());
+        }
+        return 0;
+    }
+
+    @Override
+    public void completeCandidates(Session session, CommandLine commandLine, List<Candidate> candidates) {
         // buffer could be null
         assert candidates != null;
-
-        List<Completion> completions = new ArrayList<Completion>(completers.size());
-
-        // Run each completer, saving its completion results
-        int max = -1;
         for (Completer completer : completers) {
-            Completion completion = new Completion(candidates);
-            completion.complete(session, completer, commandLine);
-
-            // Compute the max cursor position
-            if (completion.cursor > max) {
-                completions.clear();
-                completions.add(completion);
-                max = completion.cursor;
-            } else if (completion.cursor == max) {
-                completions.add(completion);
-            }
-        }
-
-        // Append candidates from completions which have the same cursor position as max
-        for (Completion completion : completions) {
-            // noinspection unchecked
-            candidates.addAll(completion.candidates);
+            completer.completeCandidates(session, commandLine, candidates);
         }
-
-        return max;
     }
 
-    private class Completion
-    {
-        public final List<String> candidates;
-
-        public int cursor;
-
-        @SuppressWarnings({ "unchecked", "rawtypes" })
-        public Completion(final List candidates) {
-            assert candidates != null;
-
-            // noinspection unchecked
-            this.candidates = new LinkedList<String>(candidates);
-        }
-
-        public void complete(final Session session, final Completer completer, final CommandLine commandLine) {
-            assert completer != null;
-
-            this.cursor = completer.complete(session, commandLine, candidates);
-        }
-    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/support/completers/FileCompleter.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/completers/FileCompleter.java b/shell/core/src/main/java/org/apache/karaf/shell/support/completers/FileCompleter.java
index 4a96d52..6bf8f4d 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/completers/FileCompleter.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/completers/FileCompleter.java
@@ -53,8 +53,7 @@ public class FileCompleter implements Completer
     private static final boolean OS_IS_WINDOWS = isWindows();
     
     public static boolean isWindows() {
-        return (OS.indexOf("win") >= 0);
-
+        return OS.contains("win");
     }
 
     public int complete(final Session session, CommandLine commandLine, final List<String> candidates) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/support/table/AnsiColumn.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/table/AnsiColumn.java b/shell/core/src/main/java/org/apache/karaf/shell/support/table/AnsiColumn.java
index 4d5b0e7..260c5c7 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/table/AnsiColumn.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/table/AnsiColumn.java
@@ -15,17 +15,17 @@
  */
 package org.apache.karaf.shell.support.table;
 
-import org.fusesource.jansi.Ansi;
+import org.jline.utils.AttributedStringBuilder;
 
 /**
  * Colored support for column.
  */
 public class AnsiColumn extends Col {
 
-    private Ansi.Color color;
+    private int color;
     private boolean bold;
 
-    public AnsiColumn(String header, Ansi.Color color, boolean bold) {
+    public AnsiColumn(String header, int color, boolean bold) {
         super(header);
         this.color = color;
         this.bold = bold;
@@ -35,20 +35,20 @@ public class AnsiColumn extends Col {
     public String getContent(String content) {
         String in = super.getContent(content);
 
-        Ansi ansi = Ansi.ansi();
-        ansi.fg(color);
+        AttributedStringBuilder sb = new AttributedStringBuilder();
+        sb.style(sb.style().foreground(color));
 
         if (bold)
-            ansi.a(Ansi.Attribute.INTENSITY_BOLD);
+            sb.style(sb.style().bold());
 
-        ansi.a(in);
+        sb.append(in);
 
         if (bold)
-            ansi.a(Ansi.Attribute.INTENSITY_BOLD_OFF);
+            sb.style(sb.style().boldOff());
 
-        ansi.fg(Ansi.Color.DEFAULT);
+        sb.style(sb.style().foregroundOff());
 
-        return ansi.toString();
+        return sb.toAnsi();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/support/terminal/SignalSupport.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/support/terminal/SignalSupport.java b/shell/core/src/main/java/org/apache/karaf/shell/support/terminal/SignalSupport.java
index 39ff0f7..b0c2b8c 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/support/terminal/SignalSupport.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/support/terminal/SignalSupport.java
@@ -22,6 +22,7 @@ import java.util.EnumSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.CopyOnWriteArraySet;
 
 import org.apache.karaf.shell.api.console.Signal;
@@ -29,11 +30,7 @@ import org.apache.karaf.shell.api.console.SignalListener;
 
 public class SignalSupport {
 
-    private final Map<Signal, Set<SignalListener>> listeners;
-
-    public SignalSupport() {
-        listeners = new ConcurrentHashMap<>(3);
-    }
+    protected final ConcurrentMap<Signal, Set<SignalListener>> listeners = new ConcurrentHashMap<>(3);
 
     public void addSignalListener(SignalListener listener, Signal... signals) {
         if (signals == null) {
@@ -80,17 +77,6 @@ public class SignalSupport {
     }
 
     protected Set<SignalListener> getSignalListeners(Signal signal, boolean create) {
-        Set<SignalListener> ls = listeners.get(signal);
-        if (ls == null && create) {
-            synchronized (listeners) {
-                ls = listeners.get(signal);
-                if (ls == null) {
-                    ls = new CopyOnWriteArraySet<>();
-                    listeners.put(signal, ls);
-                }
-            }
-        }
-        // may be null in case create=false
-        return ls;
+        return listeners.compute(signal, (sig, lst) -> lst != null ? lst : create ? new CopyOnWriteArraySet<>() : null);
     }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/test/java/org/apache/karaf/shell/impl/console/CompleterAsCompletorTest.java
----------------------------------------------------------------------
diff --git a/shell/core/src/test/java/org/apache/karaf/shell/impl/console/CompleterAsCompletorTest.java b/shell/core/src/test/java/org/apache/karaf/shell/impl/console/CompleterAsCompletorTest.java
deleted file mode 100644
index abe740a..0000000
--- a/shell/core/src/test/java/org/apache/karaf/shell/impl/console/CompleterAsCompletorTest.java
+++ /dev/null
@@ -1,60 +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.impl.console;
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class CompleterAsCompletorTest {
-
-    @Test
-    public void testCompletionMultiCommand() {
-        SessionFactoryImpl sessionFactory = new SessionFactoryImpl(new ThreadIOImpl());
-        Session session = new HeadlessSessionImpl(sessionFactory, sessionFactory.getCommandProcessor(),
-                new ByteArrayInputStream(new byte[0]), new PrintStream(new ByteArrayOutputStream()), new PrintStream(new ByteArrayOutputStream())
-        );
-
-        Completer completer = new Completer() {
-            @Override
-            public int complete(Session session, CommandLine commandLine, List<String> candidates) {
-                assertEquals(" bundle:l", commandLine.getBuffer());
-                candidates.add("bundle:list");
-                return 1;
-            }
-        };
-        jline.console.completer.Completer cmp = new CompleterAsCompletor(session, completer);
-
-        String cmd = "bundle:list ; bundle:l";
-        List<CharSequence> candidates = new ArrayList<>();
-        int pos = cmp.complete(cmd, cmd.length(), candidates);
-
-        assertEquals("bundle:list ; ".length(), pos);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/test/java/org/apache/karaf/shell/support/ansi/AnsiSplitterTest.java
----------------------------------------------------------------------
diff --git a/shell/core/src/test/java/org/apache/karaf/shell/support/ansi/AnsiSplitterTest.java b/shell/core/src/test/java/org/apache/karaf/shell/support/ansi/AnsiSplitterTest.java
index 3d490bf..c4474ec 100644
--- a/shell/core/src/test/java/org/apache/karaf/shell/support/ansi/AnsiSplitterTest.java
+++ b/shell/core/src/test/java/org/apache/karaf/shell/support/ansi/AnsiSplitterTest.java
@@ -29,7 +29,7 @@ public class AnsiSplitterTest {
     @Test
     public void testWindow() throws IOException {
         String text = "\u001B[1mThis is bold.\u001B[22m";
-        assertEquals("\u001B[1mis\u001B[22m", AnsiSplitter.substring(text, 5, 7, 4));
+        assertEquals("\u001B[1mis\u001B[0m", AnsiSplitter.substring(text, 5, 7, 4));
         assertEquals(13, AnsiSplitter.length(text, 4));
     }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/pom.xml
----------------------------------------------------------------------
diff --git a/shell/pom.xml b/shell/pom.xml
index 493a42e..f37c320 100644
--- a/shell/pom.xml
+++ b/shell/pom.xml
@@ -37,8 +37,8 @@
         <module>commands</module>
         <module>core</module>
         <module>console</module>
-        <module>ssh</module>
         <module>table</module>
+        <module>ssh</module>
     </modules>
 
 </project>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java
index 4e8dc58..f7fdf42 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/ShellFactoryImpl.java
@@ -19,7 +19,6 @@
 package org.apache.karaf.shell.ssh;
 
 import java.io.Closeable;
-import java.io.FilterOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
@@ -68,6 +67,10 @@ public class ShellFactoryImpl implements Factory<Command> {
 
         private ServerSession session;
 
+        private Session shell;
+
+        private SshTerminal terminal;
+
         private boolean closed;
 
         public void setInputStream(final InputStream in) {
@@ -94,38 +97,27 @@ public class ShellFactoryImpl implements Factory<Command> {
             try {
                 final Subject subject = ShellImpl.this.session != null ? ShellImpl.this.session
                         .getAttribute(KarafJaasAuthenticator.SUBJECT_ATTRIBUTE_KEY) : null;
-                final Terminal terminal = new SshTerminal(env);
-                Runnable destroyCallback = new Runnable() {
-                    public void run() {
-                        destroy();
-                    }
-                };
+                final PrintStream pout = out instanceof PrintStream ? (PrintStream) out : new PrintStream(out);
+                final PrintStream perr = err instanceof PrintStream ? (PrintStream) err : out == err ? pout : new PrintStream(err);
+                terminal = new SshTerminal(env, in, pout);
                 String encoding = getEncoding();
-                final Session session = sessionFactory.create(in,
-                        lfToCrLfPrintStream(out), lfToCrLfPrintStream(err), terminal, encoding, destroyCallback);
+                shell = sessionFactory.create(in,
+                        pout, perr, terminal, encoding, this::destroy);
                 for (Map.Entry<String, String> e : env.getEnv().entrySet()) {
-                    session.put(e.getKey(), e.getValue());
+                    shell.put(e.getKey(), e.getValue());
                 }
-                JaasHelper.doAs(subject, new PrivilegedAction<Object>() {
-                    public Object run() {
-                        new Thread(session, "Karaf ssh console user " + ShellUtil.getCurrentUserName()).start();
-                        return null;
-                    }
-                });
+                JaasHelper.runAs(subject, () ->
+                    new Thread(shell, "Karaf ssh console user " + ShellUtil.getCurrentUserName()).start());
             } catch (Exception e) {
                 throw (IOException) new IOException("Unable to start shell").initCause(e);
             }
         }
 
-        private PrintStream lfToCrLfPrintStream(OutputStream stream) {
-            return new PrintStream(new LfToCrLfFilterOutputStream(stream), true);
-        }
-
         public void destroy() {
             if (!closed) {
                 closed = true;
-                ShellFactoryImpl.flush(out, err);
-                ShellFactoryImpl.close(in, out, err);
+                flush(out, err);
+                close(in, out, err);
                 callback.onExit(0);
             }
         }
@@ -180,32 +172,10 @@ public class ShellFactoryImpl implements Factory<Command> {
         for (Closeable c : closeables) {
             try {
                 c.close();
-            } catch (IOException e) {
+            } catch (Exception e) {
                 // Ignore
             }
         }
     }
 
-    // TODO: remove this class when sshd use lf->crlf conversion by default
-    public class LfToCrLfFilterOutputStream extends FilterOutputStream {
-
-        private boolean lastWasCr;
-
-        public LfToCrLfFilterOutputStream(OutputStream out) {
-            super(out);
-        }
-
-        @Override
-        public void write(int b) throws IOException {
-            if (!lastWasCr && b == '\n') {
-                out.write('\r');
-                out.write('\n');
-            } else {
-                out.write(b);
-            }
-            lastWasCr = b == '\r';
-        }
-
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
index 46cd1b4..f704308 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshAction.java
@@ -34,8 +34,6 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-import jline.UnixTerminal;
-import jline.internal.TerminalLineSettings;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Argument;
 import org.apache.karaf.shell.api.action.Command;
@@ -64,6 +62,12 @@ import org.apache.sshd.common.util.SecurityUtils;
 import org.apache.sshd.common.util.buffer.Buffer;
 import org.apache.sshd.common.util.io.NoCloseInputStream;
 import org.apache.sshd.common.util.io.NoCloseOutputStream;
+import org.jline.terminal.Attributes;
+import org.jline.terminal.Attributes.ControlChar;
+import org.jline.terminal.Attributes.InputFlag;
+import org.jline.terminal.Attributes.LocalFlag;
+import org.jline.terminal.Attributes.OutputFlag;
+import org.jline.terminal.Size;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -102,7 +106,6 @@ public class SshAction implements Action {
 
     @Override
     public Object execute() throws Exception {
-
         if (hostname.indexOf('@') >= 0) {
             if (username == null) {
                 username = hostname.substring(0, hostname.indexOf('@'));
@@ -153,7 +156,6 @@ public class SshAction implements Action {
             }
             @Override
             public void serverVersionInfo(ClientSession session, List<String> lines) {
-
             }
             @Override
             public String getUpdatedPassword(ClientSession session, String prompt, String lang) {
@@ -194,110 +196,83 @@ public class SshAction implements Action {
                     channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
                 } else if (session.getTerminal() != null) {
                     final ChannelShell channel = sshSession.createShellChannel();
-                    final jline.Terminal jlineTerminal = (jline.Terminal) session.get(".jline.terminal");
-                    if (jlineTerminal instanceof UnixTerminal) {
-                        TerminalLineSettings settings = ((UnixTerminal) jlineTerminal).getSettings();
+                    final org.jline.terminal.Terminal jlineTerminal = (org.jline.terminal.Terminal) session.get(".jline.terminal");
+                    Attributes attributes = jlineTerminal.enterRawMode();
+                    try {
                         Map<PtyMode, Integer> modes = new HashMap<>();
                         // Control chars
-                        modes.put(PtyMode.VINTR, settings.getProperty("vintr"));
-                        modes.put(PtyMode.VQUIT, settings.getProperty("vquit"));
-                        modes.put(PtyMode.VERASE, settings.getProperty("verase"));
-                        modes.put(PtyMode.VKILL, settings.getProperty("vkill"));
-                        modes.put(PtyMode.VEOF, settings.getProperty("veof"));
-                        modes.put(PtyMode.VEOL, settings.getProperty("veol"));
-                        modes.put(PtyMode.VEOL2, settings.getProperty("veol2"));
-                        modes.put(PtyMode.VSTART, settings.getProperty("vstart"));
-                        modes.put(PtyMode.VSTOP, settings.getProperty("vstop"));
-                        modes.put(PtyMode.VSUSP, settings.getProperty("vsusp"));
-                        modes.put(PtyMode.VDSUSP, settings.getProperty("vdusp"));
-                        modes.put(PtyMode.VREPRINT, settings.getProperty("vreprint"));
-                        modes.put(PtyMode.VWERASE, settings.getProperty("vwerase"));
-                        modes.put(PtyMode.VLNEXT, settings.getProperty("vlnext"));
-                        modes.put(PtyMode.VSTATUS, settings.getProperty("vstatus"));
-                        modes.put(PtyMode.VDISCARD, settings.getProperty("vdiscard"));
+                        modes.put(PtyMode.VINTR, attributes.getControlChar(ControlChar.VINTR));
+                        modes.put(PtyMode.VQUIT, attributes.getControlChar(ControlChar.VQUIT));
+                        modes.put(PtyMode.VERASE, attributes.getControlChar(ControlChar.VERASE));
+                        modes.put(PtyMode.VKILL, attributes.getControlChar(ControlChar.VKILL));
+                        modes.put(PtyMode.VEOF, attributes.getControlChar(ControlChar.VEOF));
+                        modes.put(PtyMode.VEOL, attributes.getControlChar(ControlChar.VEOL));
+                        modes.put(PtyMode.VEOL2, attributes.getControlChar(ControlChar.VEOL2));
+                        modes.put(PtyMode.VSTART, attributes.getControlChar(ControlChar.VSTART));
+                        modes.put(PtyMode.VSTOP, attributes.getControlChar(ControlChar.VSTOP));
+                        modes.put(PtyMode.VSUSP, attributes.getControlChar(ControlChar.VSUSP));
+                        modes.put(PtyMode.VDSUSP, attributes.getControlChar(ControlChar.VDSUSP));
+                        modes.put(PtyMode.VREPRINT, attributes.getControlChar(ControlChar.VREPRINT));
+                        modes.put(PtyMode.VWERASE, attributes.getControlChar(ControlChar.VWERASE));
+                        modes.put(PtyMode.VLNEXT, attributes.getControlChar(ControlChar.VLNEXT));
+                        modes.put(PtyMode.VSTATUS, attributes.getControlChar(ControlChar.VSTATUS));
+                        modes.put(PtyMode.VDISCARD, attributes.getControlChar(ControlChar.VDISCARD));
                         // Input flags
-                        modes.put(PtyMode.IGNPAR, getFlag(settings, PtyMode.IGNPAR));
-                        modes.put(PtyMode.PARMRK, getFlag(settings, PtyMode.PARMRK));
-                        modes.put(PtyMode.INPCK, getFlag(settings, PtyMode.INPCK));
-                        modes.put(PtyMode.ISTRIP, getFlag(settings, PtyMode.ISTRIP));
-                        modes.put(PtyMode.INLCR, getFlag(settings, PtyMode.INLCR));
-                        modes.put(PtyMode.IGNCR, getFlag(settings, PtyMode.IGNCR));
-                        modes.put(PtyMode.ICRNL, getFlag(settings, PtyMode.ICRNL));
-                        modes.put(PtyMode.IXON, getFlag(settings, PtyMode.IXON));
-                        modes.put(PtyMode.IXANY, getFlag(settings, PtyMode.IXANY));
-                        modes.put(PtyMode.IXOFF, getFlag(settings, PtyMode.IXOFF));
+                        modes.put(PtyMode.IGNPAR, getFlag(attributes, InputFlag.IGNPAR));
+                        modes.put(PtyMode.PARMRK, getFlag(attributes, InputFlag.PARMRK));
+                        modes.put(PtyMode.INPCK, getFlag(attributes, InputFlag.INPCK));
+                        modes.put(PtyMode.ISTRIP, getFlag(attributes, InputFlag.ISTRIP));
+                        modes.put(PtyMode.INLCR, getFlag(attributes, InputFlag.INLCR));
+                        modes.put(PtyMode.IGNCR, getFlag(attributes, InputFlag.IGNCR));
+                        modes.put(PtyMode.ICRNL, getFlag(attributes, InputFlag.ICRNL));
+                        modes.put(PtyMode.IXON, getFlag(attributes, InputFlag.IXON));
+                        modes.put(PtyMode.IXANY, getFlag(attributes, InputFlag.IXANY));
+                        modes.put(PtyMode.IXOFF, getFlag(attributes, InputFlag.IXOFF));
                         // Local flags
-                        modes.put(PtyMode.ISIG, getFlag(settings, PtyMode.ISIG));
-                        modes.put(PtyMode.ICANON, getFlag(settings, PtyMode.ICANON));
-                        modes.put(PtyMode.ECHO, getFlag(settings, PtyMode.ECHO));
-                        modes.put(PtyMode.ECHOE, getFlag(settings, PtyMode.ECHOE));
-                        modes.put(PtyMode.ECHOK, getFlag(settings, PtyMode.ECHOK));
-                        modes.put(PtyMode.ECHONL, getFlag(settings, PtyMode.ECHONL));
-                        modes.put(PtyMode.NOFLSH, getFlag(settings, PtyMode.NOFLSH));
-                        modes.put(PtyMode.TOSTOP, getFlag(settings, PtyMode.TOSTOP));
-                        modes.put(PtyMode.IEXTEN, getFlag(settings, PtyMode.IEXTEN));
+                        modes.put(PtyMode.ISIG, getFlag(attributes, LocalFlag.ISIG));
+                        modes.put(PtyMode.ICANON, getFlag(attributes, LocalFlag.ICANON));
+                        modes.put(PtyMode.ECHO, getFlag(attributes, LocalFlag.ECHO));
+                        modes.put(PtyMode.ECHOE, getFlag(attributes, LocalFlag.ECHOE));
+                        modes.put(PtyMode.ECHOK, getFlag(attributes, LocalFlag.ECHOK));
+                        modes.put(PtyMode.ECHONL, getFlag(attributes, LocalFlag.ECHONL));
+                        modes.put(PtyMode.NOFLSH, getFlag(attributes, LocalFlag.NOFLSH));
+                        modes.put(PtyMode.TOSTOP, getFlag(attributes, LocalFlag.TOSTOP));
+                        modes.put(PtyMode.IEXTEN, getFlag(attributes, LocalFlag.IEXTEN));
                         // Output flags
-                        modes.put(PtyMode.OPOST, getFlag(settings, PtyMode.OPOST));
-                        modes.put(PtyMode.OLCUC, getFlag(settings, PtyMode.OLCUC));
-                        modes.put(PtyMode.ONLCR, getFlag(settings, PtyMode.ONLCR));
-                        modes.put(PtyMode.OCRNL, getFlag(settings, PtyMode.OCRNL));
-                        modes.put(PtyMode.ONOCR, getFlag(settings, PtyMode.ONOCR));
-                        modes.put(PtyMode.ONLRET, getFlag(settings, PtyMode.ONLRET));
+                        modes.put(PtyMode.OPOST, getFlag(attributes, OutputFlag.OPOST));
+                        modes.put(PtyMode.ONLCR, getFlag(attributes, OutputFlag.ONLCR));
+                        modes.put(PtyMode.OCRNL, getFlag(attributes, OutputFlag.OCRNL));
+                        modes.put(PtyMode.ONOCR, getFlag(attributes, OutputFlag.ONOCR));
+                        modes.put(PtyMode.ONLRET, getFlag(attributes, OutputFlag.ONLRET));
                         channel.setPtyModes(modes);
-                    } else if (session.getTerminal() instanceof SshTerminal) {
-                        channel.setPtyModes(((SshTerminal) session.getTerminal()).getEnvironment().getPtyModes());
-                    } else {
-                        channel.setupSensibleDefaultPty();
-                    }
-                    channel.setPtyColumns(getTermWidth());
-                    channel.setPtyLines(getTermHeight());
-                    channel.setAgentForwarding(true);
-                    channel.setEnv("TERM", session.getTerminal().getType());
-                    Object ctype = session.get("LC_CTYPE");
-                    if (ctype != null) {
-                        channel.setEnv("LC_CTYPE", ctype.toString());
-                    }
-                    channel.setIn(new NoCloseInputStream(System.in));
-                    channel.setOut(new NoCloseOutputStream(System.out));
-                    channel.setErr(new NoCloseOutputStream(System.err));
-                    channel.open().verify();
-                    SignalListener signalListener = new SignalListener() {
-                        @Override
-                        public void signal(Signal signal) {
+                        channel.setPtyColumns(getTermWidth());
+                        channel.setPtyLines(getTermHeight());
+                        channel.setAgentForwarding(true);
+                        channel.setEnv("TERM", session.getTerminal().getType());
+                        Object ctype = session.get("LC_CTYPE");
+                        if (ctype != null) {
+                            channel.setEnv("LC_CTYPE", ctype.toString());
+                        }
+                        channel.setIn(new NoCloseInputStream(System.in));
+                        channel.setOut(new NoCloseOutputStream(System.out));
+                        channel.setErr(new NoCloseOutputStream(System.err));
+                        channel.open().verify();
+                        SignalListener signalListener = signal -> {
                             try {
-                                // Ugly hack to force the jline unix terminal to retrieve the width/height of the terminal
-                                // because results are cached for 1 second.
-                                try {
-                                    Field field = jlineTerminal.getClass().getSuperclass().getDeclaredField("settings");
-                                    field.setAccessible(true);
-                                    Object settings = field.get(jlineTerminal);
-                                    field = settings.getClass().getDeclaredField("configLastFetched");
-                                    field.setAccessible(true);
-                                    field.setLong(settings, 0L);
-                                } catch (Throwable t) {
-                                    // Ignore
-                                }
-                                // TODO: replace with PtyCapableChannelSession#sendWindowChange
-                                org.apache.sshd.common.session.Session sshSession = channel.getSession();
-                                Buffer buffer = sshSession.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST);
-                                buffer.putInt(channel.getRecipient());
-                                buffer.putString("window-change");
-                                buffer.putBoolean(false);
-                                buffer.putInt(session.getTerminal().getWidth());
-                                buffer.putInt(session.getTerminal().getHeight());
-                                buffer.putInt(0);
-                                buffer.putInt(0);
-                                sshSession.writePacket(buffer);
+                                Size size = jlineTerminal.getSize();
+                                channel.sendWindowChange(size.getColumns(), size.getRows());
                             } catch (IOException e) {
                                 // Ignore
                             }
+                        };
+                        session.getTerminal().addSignalListener(signalListener, Signal.WINCH);
+                        try {
+                            channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
+                        } finally {
+                            session.getTerminal().removeSignalListener(signalListener);
                         }
-                    };
-                    session.getTerminal().addSignalListener(signalListener, Signal.WINCH);
-                    try {
-                        channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
                     } finally {
-                        session.getTerminal().removeSignalListener(signalListener);
+                        jlineTerminal.setAttributes(attributes);
                     }
                 } else {
                     throw new IllegalStateException("No terminal for interactive ssh session");
@@ -313,11 +288,19 @@ public class SshAction implements Action {
         return null;
     }
 
-    private int getFlag(TerminalLineSettings settings, PtyMode mode) {
-        String name = mode.toString().toLowerCase();
-        return (settings.getPropertyAsString(name) != null) ? 1 : 0;
+    private static int getFlag(Attributes attributes, InputFlag flag) {
+        return attributes.getInputFlag(flag) ? 1 : 0;
+    }
+
+    private static int getFlag(Attributes attributes, OutputFlag flag) {
+        return attributes.getOutputFlag(flag) ? 1 : 0;
     }
 
+    private static int getFlag(Attributes attributes, LocalFlag flag) {
+        return attributes.getLocalFlag(flag) ? 1 : 0;
+    }
+
+
     private int getTermWidth() {
         Terminal term = session.getTerminal();
         return term != null ? term.getWidth() : 80;

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshTerminal.java
----------------------------------------------------------------------
diff --git a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshTerminal.java b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshTerminal.java
index 4b7aff6..ebd9e22 100644
--- a/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshTerminal.java
+++ b/shell/ssh/src/main/java/org/apache/karaf/shell/ssh/SshTerminal.java
@@ -18,53 +18,164 @@
  */
 package org.apache.karaf.shell.ssh;
 
-import org.apache.karaf.shell.api.console.Signal;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.EnumSet;
+import java.util.Map;
+
+import org.apache.karaf.shell.api.console.SignalListener;
 import org.apache.karaf.shell.api.console.Terminal;
-import org.apache.karaf.shell.support.terminal.SignalSupport;
 import org.apache.sshd.common.channel.PtyMode;
 import org.apache.sshd.server.Environment;
+import org.jline.terminal.Attributes.ControlChar;
+import org.jline.terminal.Attributes.InputFlag;
+import org.jline.terminal.Attributes.LocalFlag;
+import org.jline.terminal.Attributes.OutputFlag;
+import org.jline.terminal.Size;
+import org.jline.terminal.impl.ExternalTerminal;
 
-public class SshTerminal extends SignalSupport implements Terminal {
+public class SshTerminal extends ExternalTerminal implements Terminal {
 
     private Environment environment;
-    private boolean echo;
 
-    public SshTerminal(Environment environment) {
+    public SshTerminal(Environment environment, InputStream input, OutputStream output) throws IOException {
+        super("Karaf SSH terminal",
+              environment.getEnv().get(Environment.ENV_TERM),
+              input,
+              output,
+              "UTF-8");
         this.environment = environment;
-        this.environment.addSignalListener(new org.apache.sshd.server.SignalListener() {
-            @Override
-            public void signal(org.apache.sshd.server.Signal signal) {
-                SshTerminal.this.signal(Signal.WINCH);
+        this.environment.addSignalListener(this::handleSignal);
+        for (Map.Entry<PtyMode, Integer> e : environment.getPtyModes().entrySet()) {
+            switch (e.getKey()) {
+                case VINTR:
+                    attributes.setControlChar(ControlChar.VINTR, e.getValue());
+                    break;
+                case VQUIT:
+                    attributes.setControlChar(ControlChar.VQUIT, e.getValue());
+                    break;
+                case VERASE:
+                    attributes.setControlChar(ControlChar.VERASE, e.getValue());
+                    break;
+                case VKILL:
+                    attributes.setControlChar(ControlChar.VKILL, e.getValue());
+                    break;
+                case VEOF:
+                    attributes.setControlChar(ControlChar.VEOF, e.getValue());
+                    break;
+                case VEOL:
+                    attributes.setControlChar(ControlChar.VEOL, e.getValue());
+                    break;
+                case VEOL2:
+                    attributes.setControlChar(ControlChar.VEOL2, e.getValue());
+                    break;
+                case VSTART:
+                    attributes.setControlChar(ControlChar.VSTART, e.getValue());
+                    break;
+                case VSTOP:
+                    attributes.setControlChar(ControlChar.VSTOP, e.getValue());
+                    break;
+                case VSUSP:
+                    attributes.setControlChar(ControlChar.VSUSP, e.getValue());
+                    break;
+                case VDSUSP:
+                    attributes.setControlChar(ControlChar.VDSUSP, e.getValue());
+                    break;
+                case VREPRINT:
+                    attributes.setControlChar(ControlChar.VREPRINT, e.getValue());
+                    break;
+                case VWERASE:
+                    attributes.setControlChar(ControlChar.VWERASE, e.getValue());
+                    break;
+                case VLNEXT:
+                    attributes.setControlChar(ControlChar.VLNEXT, e.getValue());
+                    break;
+                case VSTATUS:
+                    attributes.setControlChar(ControlChar.VSTATUS, e.getValue());
+                    break;
+                case VDISCARD:
+                    attributes.setControlChar(ControlChar.VDISCARD, e.getValue());
+                    break;
+                case ECHO:
+                    attributes.setLocalFlag(LocalFlag.ECHO, e.getValue() != 0);
+                    break;
+                case ICANON:
+                    attributes.setLocalFlag(LocalFlag.ICANON, e.getValue() != 0);
+                    break;
+                case ISIG:
+                    attributes.setLocalFlag(LocalFlag.ISIG, e.getValue() != 0);
+                    break;
+                case ICRNL:
+                    attributes.setInputFlag(InputFlag.ICRNL, e.getValue() != 0);
+                    break;
+                case INLCR:
+                    attributes.setInputFlag(InputFlag.INLCR, e.getValue() != 0);
+                    break;
+                case IGNCR:
+                    attributes.setInputFlag(InputFlag.IGNCR, e.getValue() != 0);
+                    break;
+                case OCRNL:
+                    attributes.setOutputFlag(OutputFlag.OCRNL, e.getValue() != 0);
+                    break;
+                case ONLCR:
+                    attributes.setOutputFlag(OutputFlag.ONLCR, e.getValue() != 0);
+                    break;
+                case ONLRET:
+                    attributes.setOutputFlag(OutputFlag.ONLRET, e.getValue() != 0);
+                    break;
+                case OPOST:
+                    attributes.setOutputFlag(OutputFlag.OPOST, e.getValue() != 0);
+                    break;
             }
-        }, org.apache.sshd.server.Signal.WINCH);
-        this.echo = environment.getPtyModes().containsKey(PtyMode.ECHO);
+        }
     }
 
-    @Override
-    public String getType() {
-        return environment.getEnv().get(Environment.ENV_TERM);
+    protected void handleSignal(org.apache.sshd.server.Signal signal) {
+        if (signal == org.apache.sshd.server.Signal.INT) {
+            raise(Signal.INT);
+        } else if (signal == org.apache.sshd.server.Signal.QUIT) {
+            raise(Signal.QUIT);
+        } else if (signal == org.apache.sshd.server.Signal.TSTP) {
+            raise(Signal.TSTP);
+        } else if (signal == org.apache.sshd.server.Signal.CONT) {
+            raise(Signal.CONT);
+        } else if (signal == org.apache.sshd.server.Signal.WINCH) {
+            int w = Integer.valueOf(this.environment.getEnv().get(Environment.ENV_COLUMNS));
+            int h = Integer.valueOf(this.environment.getEnv().get(Environment.ENV_LINES));
+            setSize(new Size(w, h));
+            raise(Signal.WINCH);
+        }
     }
 
     @Override
     public int getWidth() {
-        int width = 0;
-        try {
-            width = Integer.valueOf(this.environment.getEnv().get(Environment.ENV_COLUMNS));
-        } catch (Throwable t) {
-            // Ignore
-        }
-        return width > 0 ? width : 80;
+        return size.getColumns();
     }
 
     @Override
     public int getHeight() {
-        int height = 0;
-        try {
-            height = Integer.valueOf(this.environment.getEnv().get(Environment.ENV_LINES));
-        } catch (Throwable t) {
-            // Ignore
-        }
-        return height > 0 ? height : 24;
+        return size.getRows();
+    }
+
+    @Override
+    public void addSignalListener(SignalListener listener) {
+        // TODO:JLINE
+    }
+
+    @Override
+    public void addSignalListener(SignalListener listener, org.apache.karaf.shell.api.console.Signal... signal) {
+        // TODO:JLINE
+    }
+
+    @Override
+    public void addSignalListener(SignalListener listener, EnumSet<org.apache.karaf.shell.api.console.Signal> signals) {
+        // TODO:JLINE
+    }
+
+    @Override
+    public void removeSignalListener(SignalListener listener) {
+        // TODO:JLINE
     }
 
     @Override
@@ -74,16 +185,12 @@ public class SshTerminal extends SignalSupport implements Terminal {
 
     @Override
     public boolean isEchoEnabled() {
-        return echo;
+        return echo();
     }
 
     @Override
     public void setEchoEnabled(boolean enabled) {
-        echo = enabled;
-    }
-
-    public Environment getEnvironment() {
-        return environment;
+        echo(enabled);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java
----------------------------------------------------------------------
diff --git a/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java b/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java
index a4d2f13..2cb96ca 100644
--- a/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java
+++ b/util/src/main/java/org/apache/karaf/util/jaas/JaasHelper.java
@@ -73,6 +73,14 @@ public class JaasHelper {
         return false;
     }
 
+    public static void runAs(final Subject subject,
+                             final Runnable action) {
+        if (action == null) {
+            throw new NullPointerException();
+        }
+        doAs(subject, (PrivilegedAction<Object>)(() -> { action.run(); return null; } ));
+    }
+
     public static <T> T doAs(final Subject subject,
                              final PrivilegedAction<T> action) {
         if (action == null) {

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/webconsole/gogo/pom.xml
----------------------------------------------------------------------
diff --git a/webconsole/gogo/pom.xml b/webconsole/gogo/pom.xml
index 83d40b6..566f272 100644
--- a/webconsole/gogo/pom.xml
+++ b/webconsole/gogo/pom.xml
@@ -83,6 +83,10 @@
             <artifactId>org.apache.karaf.shell.console</artifactId>
         </dependency>
         <dependency>
+            <groupId>jline</groupId>
+            <artifactId>jline</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.apache.karaf</groupId>
             <artifactId>org.apache.karaf.util</artifactId>
             <scope>provided</scope>
@@ -122,7 +126,6 @@
                 <configuration>
                     <instructions>
                         <Import-Package>
-                            jline;version="[${jline.version}, ${jline.version}]",
 			                org.apache.felix.webconsole*;version="[3,5)",
                             *
                         </Import-Package>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java
----------------------------------------------------------------------
diff --git a/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java b/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java
index e6e826b..7b285c1 100644
--- a/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java
+++ b/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/GogoPlugin.java
@@ -26,6 +26,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.InterruptedIOException;
+import java.io.OutputStream;
 import java.io.PipedInputStream;
 import java.io.PipedOutputStream;
 import java.io.PrintStream;
@@ -183,13 +184,15 @@ public class GogoPlugin extends AbstractWebConsolePlugin {
 
                 in = new PipedOutputStream();
                 out = new PipedInputStream();
-                PrintStream pipedOut = new PrintStream(new PipedOutputStream(out), true);
+                InputStream input = new PipedInputStream(in);
+                OutputStream output = new PipedOutputStream(out);
+                PrintStream pipedOut = new PrintStream(output, true);
                 
                 Session session = sessionFactory.create(
-                        new PipedInputStream(in),
+                        input,
                         pipedOut,
                         pipedOut,
-                        new WebTerminal(TERM_WIDTH, TERM_HEIGHT),
+                        new WebTerminal(TERM_WIDTH, TERM_HEIGHT, input, pipedOut),
                         null,
                         null);
                 new Thread(session, "Karaf web console user " + getCurrentUserName()).start();

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/WebTerminal.java
----------------------------------------------------------------------
diff --git a/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/WebTerminal.java b/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/WebTerminal.java
index 4ac8923..e7fe2a8 100644
--- a/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/WebTerminal.java
+++ b/webconsole/gogo/src/main/java/org/apache/karaf/webconsole/gogo/WebTerminal.java
@@ -16,46 +16,67 @@
  */
 package org.apache.karaf.webconsole.gogo;
 
+ import java.io.IOException;
+ import java.io.InputStream;
+ import java.io.OutputStream;
+ import java.util.EnumSet;
+
+ import org.apache.karaf.shell.api.console.Signal;
+ import org.apache.karaf.shell.api.console.SignalListener;
  import org.apache.karaf.shell.api.console.Terminal;
- import org.apache.karaf.shell.support.terminal.SignalSupport;
+ import org.jline.terminal.impl.ExternalTerminal;
 
-public class WebTerminal extends SignalSupport implements Terminal {
+public class WebTerminal extends ExternalTerminal implements Terminal {
 
-    private int width;
-    private int height;
-    private boolean echo = true;
+    public WebTerminal(int width, int height, InputStream input, OutputStream output) throws IOException {
+        super("Karaf Web Terminal", "ansi", input, output, "UTF-8");
+        size.setColumns(width);
+        size.setRows(height);
+    }
 
-    public WebTerminal(int width, int height) {
-        this.width = width;
-        this.height = height;
+    @Override
+    public int getWidth() {
+        return size.getColumns();
     }
 
     @Override
-    public String getType() {
-        return "ansi";
+    public int getHeight() {
+        return size.getRows();
     }
 
     @Override
-    public boolean isAnsiSupported() {
-        return true;
+    public void addSignalListener(SignalListener listener) {
+        // TODO:JLINE
     }
 
     @Override
-    public boolean isEchoEnabled() {
-        return echo;
+    public void addSignalListener(SignalListener listener, org.apache.karaf.shell.api.console.Signal... signal) {
+        // TODO:JLINE
     }
 
     @Override
-    public void setEchoEnabled(boolean enabled) {
-        echo = enabled;
+    public void addSignalListener(SignalListener listener, EnumSet<org.apache.karaf.shell.api.console.Signal> signals) {
+        // TODO:JLINE
     }
 
-    public int getWidth() {
-        return width;
+    @Override
+    public void removeSignalListener(SignalListener listener) {
+        // TODO:JLINE
     }
 
-    public int getHeight() {
-        return height;
+    @Override
+    public boolean isAnsiSupported() {
+        return true;
+    }
+
+    @Override
+    public boolean isEchoEnabled() {
+        return echo();
+    }
+
+    @Override
+    public void setEchoEnabled(boolean enabled) {
+        echo(enabled);
     }
 
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
----------------------------------------------------------------------
diff --git a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
index a4832c8..492a479 100644
--- a/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
+++ b/wrapper/src/main/java/org/apache/karaf/wrapper/internal/WrapperServiceImpl.java
@@ -16,8 +16,8 @@
  */
 package org.apache.karaf.wrapper.internal;
 
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
 import org.apache.karaf.wrapper.WrapperService;
-import org.fusesource.jansi.Ansi;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -302,8 +302,8 @@ public class WrapperServiceImpl implements WrapperService {
     private void mkdir(File file) {
         if (!file.exists()) {
             LOGGER.info("Creating missing directory: {}", file.getPath());
-            System.out.println(Ansi.ansi().a("Creating missing directory: ")
-                    .a(Ansi.Attribute.INTENSITY_BOLD).a(file.getPath()).a(Ansi.Attribute.RESET).toString());
+            System.out.println("Creating missing directory: "
+                    + SimpleAnsi.INTENSITY_BOLD + file.getPath() + SimpleAnsi.INTENSITY_NORMAL);
             file.mkdirs();
         }
     }
@@ -311,8 +311,8 @@ public class WrapperServiceImpl implements WrapperService {
     private void copyResourceTo(File outFile, String resource, boolean text) throws Exception {
         if (!outFile.exists()) {
             LOGGER.info("Creating file: {}", outFile.getPath());
-            System.out.println(Ansi.ansi().a("Creating file: ")
-                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            System.out.println("Creating file: "
+                    + SimpleAnsi.INTENSITY_BOLD + outFile.getPath() + SimpleAnsi.INTENSITY_NORMAL);
             InputStream is = WrapperServiceImpl.class.getResourceAsStream(resource);
             if (is == null) {
                 throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
@@ -348,17 +348,17 @@ public class WrapperServiceImpl implements WrapperService {
             }
         } else {
             LOGGER.warn("File already exists. Move it out of the way if you wish to recreate it: {}", outFile.getPath());
-            System.out.println(Ansi.ansi()
-                    .fg(Ansi.Color.RED).a("File already exists").a(Ansi.Attribute.RESET)
-                    .a(". Move it out of the way if you wish to recreate it: ").a(outFile.getPath()).toString());
+            System.out.println(
+                    SimpleAnsi.COLOR_RED + "File already exists" + SimpleAnsi.COLOR_DEFAULT
+                            + ". Move it out of the way if you wish to recreate it: " + outFile.getPath());
         }
     }
 
     private void copyFilteredResourceTo(File outFile, String resource, HashMap<String, String> props, String[] envs, String[] includes) throws Exception {
         if (!outFile.exists()) {
             LOGGER.info("Creating file: {}", outFile.getPath());
-            System.out.println(Ansi.ansi().a("Creating file: ")
-                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            System.out.println("Creating file: "
+                    + SimpleAnsi.INTENSITY_BOLD + outFile.getPath() + SimpleAnsi.INTENSITY_NORMAL);
             InputStream is = WrapperServiceImpl.class.getResourceAsStream(resource);
             if (is == null) {
                 throw new IllegalArgumentException("Resource " + resource + " doesn't exist");
@@ -393,9 +393,9 @@ public class WrapperServiceImpl implements WrapperService {
             }
         } else {
             LOGGER.warn("File already exists. Move it out of the way if you wish to recreate it: {}", outFile.getPath());
-            System.out.println(Ansi.ansi()
-                    .fg(Ansi.Color.RED).a("File already exists").a(Ansi.Attribute.RESET)
-                    .a(". Move it out of the way if you wish to recreate it: ").a(outFile.getPath()).toString());
+            System.out.println(
+                    SimpleAnsi.COLOR_RED + "File already exists" + SimpleAnsi.COLOR_DEFAULT
+                            + ". Move it out of the way if you wish to recreate it: " + outFile.getPath());
         }
     }
 
@@ -441,8 +441,8 @@ public class WrapperServiceImpl implements WrapperService {
     private void createJar(File outFile, String resource) throws Exception {
         if (!outFile.exists()) {
             LOGGER.info("Creating file: {}", outFile.getPath());
-            System.out.println(Ansi.ansi().a("Creating file: ")
-                    .a(Ansi.Attribute.INTENSITY_BOLD).a(outFile.getPath()).a(Ansi.Attribute.RESET).toString());
+            System.out.println("Creating file: "
+                    + SimpleAnsi.INTENSITY_BOLD + outFile.getPath() + SimpleAnsi.INTENSITY_NORMAL);
             InputStream is = getClass().getClassLoader().getResourceAsStream(resource);
             if (is == null) {
                 throw new IllegalStateException("Resource " + resource + " not found!");


[6/6] karaf git commit: [KARAF-4570] Upgrade to JLine 3

Posted by gn...@apache.org.
[KARAF-4570] Upgrade to JLine 3

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

Branch: refs/heads/master
Commit: b4ae5245cbec658e6be2b1df6366786a4c6824ab
Parents: d4002ba
Author: Guillaume Nodet <gn...@apache.org>
Authored: Tue Jun 14 11:54:43 2016 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Jun 14 15:23:00 2016 +0200

----------------------------------------------------------------------
 assemblies/apache-karaf-minimal/pom.xml         |   1 +
 assemblies/apache-karaf/pom.xml                 |   1 +
 assemblies/features/framework/pom.xml           |   4 -
 .../standard/src/main/feature/feature.xml       |   2 +-
 .../apache/karaf/bundle/command/Classes.java    |   7 +-
 .../apache/karaf/bundle/command/Headers.java    |  13 +-
 .../main/java/org/apache/karaf/client/Main.java | 399 +++------
 demos/profiles/registry/pom.xml                 |   2 +-
 .../completers/FeatureCompleterSupport.java     |  25 +-
 .../core/internal/InstanceServiceImpl.java      |  10 +-
 .../org/apache/karaf/instance/main/Execute.java |   3 -
 .../org/apache/karaf/itests/FeatureTest.java    |   4 +-
 main/pom.xml                                    |   2 +-
 pom.xml                                         |  36 +-
 profile/pom.xml                                 |   6 -
 .../karaf/profile/command/ProfileEdit.java      |  39 +-
 shell/commands/pom.xml                          |   7 -
 .../karaf/shell/commands/impl/DateAction.java   | 125 +--
 .../karaf/shell/commands/impl/EditAction.java   | 149 +---
 .../karaf/shell/commands/impl/GrepAction.java   |  15 +-
 .../shell/commands/impl/HistoryAction.java      |  26 +-
 .../karaf/shell/commands/impl/InfoAction.java   |   8 +-
 .../karaf/shell/commands/impl/LessAction.java   | 852 +------------------
 shell/console/pom.xml                           |  12 +-
 .../karaf/shell/commands/ansi/SimpleAnsi.java   |  13 +-
 .../shell/console/factory/ConsoleFactory.java   |  31 -
 .../apache/karaf/shell/console/impl/Main.java   | 348 --------
 .../shell/console/impl/jline/Branding.java      |  93 --
 .../impl/jline/CompleterAsCompletor.java        |  34 -
 .../impl/jline/ConsoleFactoryService.java       |  98 ---
 .../shell/console/impl/jline/ConsoleImpl.java   | 599 -------------
 .../console/impl/jline/DelayedStarted.java      |  87 --
 .../console/impl/jline/KarafFileHistory.java    |  65 --
 .../console/impl/jline/LocalConsoleManager.java | 163 ----
 .../console/impl/jline/StreamWrapUtil.java      |  92 --
 .../console/impl/jline/TerminalFactory.java     |  47 -
 .../karaf/shell/commands/basic/Context.java     |  67 --
 .../shell/commands/basic/SimpleSubShell.java    |  39 -
 .../shell/commands/basic/TestCommands.java      | 184 ----
 .../shell/commands/meta/TestFormatting.java     |  35 -
 .../completer/ArgumentCompleterTest.java        | 145 ----
 .../console/completer/BooleanCompleterTest.java |  62 --
 .../console/completer/CompleterTestSupport.java |  34 -
 .../console/completer/CompleterValuesTest.java  |  74 --
 .../shell/console/completer/CompletionTest.java | 172 ----
 .../console/completer/DummyCommandSession.java  |  48 --
 .../console/completer/FileCompleterTest.java    |  56 --
 .../shell/console/impl/ExampleSubclassMain.java | 104 ---
 .../console/impl/jline/ConsoleImplTest.java     | 195 -----
 .../SecuredCommandConfigTransformerTest.java    | 281 ------
 .../impl/SecuredCommandProcessorImplTest.java   | 142 ----
 shell/core/pom.xml                              |   8 +
 .../karaf/shell/api/console/Candidate.java      |  78 ++
 .../karaf/shell/api/console/Completer.java      |   8 +
 .../apache/karaf/shell/api/console/Session.java |   3 +-
 .../impl/action/command/ActionCommand.java      |   9 +
 .../impl/action/command/ArgumentCompleter.java  |  85 +-
 .../shell/impl/console/CommandsCompleter.java   | 128 ++-
 .../impl/console/CompleterAsCompletor.java      |  51 --
 .../shell/impl/console/ConsoleSessionImpl.java  | 307 ++-----
 .../shell/impl/console/HeadlessSessionImpl.java |   1 +
 .../shell/impl/console/HistoryWrapper.java      |   4 +-
 .../karaf/shell/impl/console/JLineTerminal.java | 246 ++++--
 .../shell/impl/console/KarafFileHistory.java    |  64 --
 .../karaf/shell/impl/console/KarafTerminal.java |  62 +-
 .../shell/impl/console/TerminalFactory.java     |  47 -
 .../help/wikidoc/AnsiPrintingWikiVisitor.java   |  24 +-
 .../shell/impl/console/osgi/Activator.java      |   8 +-
 .../impl/console/osgi/LocalConsoleManager.java  |  16 +-
 .../shell/impl/console/osgi/StreamWrapUtil.java |  91 --
 .../shell/impl/console/standalone/Main.java     |  36 +-
 .../karaf/shell/support/ansi/AnsiSplitter.java  | 382 ++-------
 .../karaf/shell/support/ansi/SimpleAnsi.java    |  16 +-
 .../support/completers/AggregateCompleter.java  |  59 +-
 .../shell/support/completers/FileCompleter.java |   3 +-
 .../karaf/shell/support/table/AnsiColumn.java   |  20 +-
 .../shell/support/terminal/SignalSupport.java   |  20 +-
 .../impl/console/CompleterAsCompletorTest.java  |  60 --
 .../shell/support/ansi/AnsiSplitterTest.java    |   2 +-
 shell/pom.xml                                   |   2 +-
 .../karaf/shell/ssh/ShellFactoryImpl.java       |  60 +-
 .../org/apache/karaf/shell/ssh/SshAction.java   | 181 ++--
 .../org/apache/karaf/shell/ssh/SshTerminal.java | 175 +++-
 .../org/apache/karaf/util/jaas/JaasHelper.java  |   8 +
 webconsole/gogo/pom.xml                         |   5 +-
 .../karaf/webconsole/gogo/GogoPlugin.java       |   9 +-
 .../karaf/webconsole/gogo/WebTerminal.java      |  61 +-
 .../wrapper/internal/WrapperServiceImpl.java    |  30 +-
 88 files changed, 1330 insertions(+), 6095 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/assemblies/apache-karaf-minimal/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf-minimal/pom.xml b/assemblies/apache-karaf-minimal/pom.xml
index 93b021b..ac20996 100644
--- a/assemblies/apache-karaf-minimal/pom.xml
+++ b/assemblies/apache-karaf-minimal/pom.xml
@@ -139,6 +139,7 @@
                         <feature>service</feature>
                         <feature>system</feature>
                     </bootFeatures>
+                    <javase>1.8</javase>
                 </configuration>
             </plugin>
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/assemblies/apache-karaf/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/apache-karaf/pom.xml b/assemblies/apache-karaf/pom.xml
index 707d79f..c5b5987 100644
--- a/assemblies/apache-karaf/pom.xml
+++ b/assemblies/apache-karaf/pom.xml
@@ -206,6 +206,7 @@
                         <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.activator/${servicemix.specs.version};type:=default;export:=true</library>
                         <library>mvn:org.apache.servicemix.specs/org.apache.servicemix.specs.locator/${servicemix.specs.version};type:=default;export:=true</library>
                     </libraries>
+                    <javase>1.8</javase>
                 </configuration>
             </plugin>
         </plugins>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/assemblies/features/framework/pom.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/framework/pom.xml b/assemblies/features/framework/pom.xml
index 42b150e..9f4a19f 100644
--- a/assemblies/features/framework/pom.xml
+++ b/assemblies/features/framework/pom.xml
@@ -85,10 +85,6 @@
             <groupId>jline</groupId>
             <artifactId>jline</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.jledit</groupId>
-            <artifactId>core</artifactId>
-        </dependency>
 
         <!-- listed in source feature.xml with explicit startlevel -->
         <dependency>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/assemblies/features/standard/src/main/feature/feature.xml
----------------------------------------------------------------------
diff --git a/assemblies/features/standard/src/main/feature/feature.xml b/assemblies/features/standard/src/main/feature/feature.xml
index 4447b72..dd260a9 100644
--- a/assemblies/features/standard/src/main/feature/feature.xml
+++ b/assemblies/features/standard/src/main/feature/feature.xml
@@ -101,8 +101,8 @@
             new = admin
             java = admin
         </config>
+        <bundle dependency="true" start-level="30">mvn:org.fusesource.jansi/jansi/${jansi.version}</bundle>
         <bundle dependency="true" start-level="30">mvn:jline/jline/${jline.version}</bundle>
-        <bundle dependency="true" start-level="30">mvn:org.jledit/core/${jledit.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.core/${project.version}</bundle>
         <bundle start-level="30">mvn:org.apache.karaf.shell/org.apache.karaf.shell.commands/${project.version}</bundle>
     </feature>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
index a79dd58..72d987c 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Classes.java
@@ -21,13 +21,10 @@ import java.util.Collection;
 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.apache.karaf.shell.support.ansi.SimpleAnsi;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.wiring.BundleWiring;
 
-import static org.fusesource.jansi.Ansi.Attribute.INTENSITY_BOLD;
-import static org.fusesource.jansi.Ansi.Attribute.RESET;
-import static org.fusesource.jansi.Ansi.ansi;
-
 @Command(scope = "bundle", name = "classes", description = "Displays a list of classes/resources contained in the bundle")
 @Service
 public class Classes extends BundlesCommand {
@@ -53,7 +50,7 @@ public class Classes extends BundlesCommand {
             }
             for (String resource:resources){
                 if (localResources.contains(resource)) {
-                    System.out.println(ansi().a(INTENSITY_BOLD).a(resource).a(RESET));
+                    System.out.println(SimpleAnsi.INTENSITY_BOLD + resource + SimpleAnsi.INTENSITY_NORMAL);
                 } else {
                     System.out.println(resource);
                 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
----------------------------------------------------------------------
diff --git a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
index 71ea0bb..1e88696 100644
--- a/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
+++ b/bundle/core/src/main/java/org/apache/karaf/bundle/command/Headers.java
@@ -38,7 +38,7 @@ 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.Terminal;
 import org.apache.karaf.shell.support.ShellUtil;
-import org.fusesource.jansi.Ansi;
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.Constants;
 import org.osgi.framework.wiring.BundleCapability;
@@ -174,22 +174,21 @@ public class Headers extends BundlesCommand {
         formatters.put(REQUIRE_BUNDLE_ATTRIB, new ClauseFormatter() {
             public void pre(Clause clause, StringBuilder output) {
                 boolean isSatisfied = checkBundle(clause.getName(), clause.getAttribute("bundle-version"));
-                Ansi.ansi(output).fg(isSatisfied ? Ansi.Color.DEFAULT : Ansi.Color.RED).a("");
+                output.append(isSatisfied ? SimpleAnsi.COLOR_DEFAULT : SimpleAnsi.COLOR_RED);
             }
             public void post(Clause clause, StringBuilder output) {
-                Ansi.ansi(output).reset().a("");
+                output.append(SimpleAnsi.RESET);
             }
         });
         formatters.put(IMPORT_PACKAGES_ATTRIB, new ClauseFormatter() {
             public void pre(Clause clause, StringBuilder output) {
                 boolean isSatisfied = checkPackage(clause.getName(), clause.getAttribute("version"));
                 boolean isOptional = "optional".equals(clause.getDirective("resolution"));
-                Ansi.ansi(output).fg(isSatisfied ? Ansi.Color.DEFAULT : Ansi.Color.RED)
-                                 .a(isSatisfied || isOptional ? Ansi.Attribute.INTENSITY_BOLD_OFF : Ansi.Attribute.INTENSITY_BOLD)
-                                 .a("");
+                output.append(isSatisfied ? SimpleAnsi.COLOR_DEFAULT : SimpleAnsi.COLOR_RED);
+                output.append(isSatisfied || isOptional ? SimpleAnsi.INTENSITY_NORMAL : SimpleAnsi.INTENSITY_BOLD);
             }
             public void post(Clause clause, StringBuilder output) {
-                Ansi.ansi(output).reset().a("");
+                output.append(SimpleAnsi.RESET);
             }
         });
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/client/src/main/java/org/apache/karaf/client/Main.java
----------------------------------------------------------------------
diff --git a/client/src/main/java/org/apache/karaf/client/Main.java b/client/src/main/java/org/apache/karaf/client/Main.java
index 89cb9f4..0d704a2 100644
--- a/client/src/main/java/org/apache/karaf/client/Main.java
+++ b/client/src/main/java/org/apache/karaf/client/Main.java
@@ -16,32 +16,35 @@
  */
 package org.apache.karaf.client;
 
-import java.io.*;
+import java.io.BufferedReader;
+import java.io.ByteArrayInputStream;
 import java.io.Closeable;
-import java.lang.reflect.Field;
+import java.io.Console;
+import java.io.FileInputStream;
+import java.io.FilterInputStream;
+import java.io.IOError;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.InterruptedIOException;
+import java.io.ObjectInputStream;
+import java.io.Reader;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
 import java.net.URL;
+import java.nio.charset.Charset;
 import java.nio.file.Paths;
 import java.security.KeyPair;
-import java.nio.charset.Charset;
-import java.util.Arrays;
+import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
-import java.util.Collections;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.ArrayBlockingQueue;
 import java.util.concurrent.BlockingQueue;
 
-import jline.NoInterruptUnixTerminal;
-import jline.Terminal;
-import jline.TerminalFactory;
-
-import jline.UnixTerminal;
-import jline.internal.TerminalLineSettings;
 import org.apache.sshd.agent.SshAgent;
 import org.apache.sshd.agent.local.AgentImpl;
 import org.apache.sshd.agent.local.LocalAgentFactory;
@@ -49,27 +52,25 @@ import org.apache.sshd.client.ClientBuilder;
 import org.apache.sshd.client.SshClient;
 import org.apache.sshd.client.auth.keyboard.UserInteraction;
 import org.apache.sshd.client.channel.ChannelShell;
-import org.apache.sshd.client.channel.ClientChannelEvent;
-import org.apache.sshd.client.channel.PtyCapableChannelSession;
-import org.apache.sshd.client.future.ConnectFuture;
-import org.apache.sshd.common.FactoryManager;
-import org.apache.sshd.common.NamedFactory;
-import org.apache.sshd.common.RuntimeSshException;
-import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.client.channel.ClientChannel;
+import org.apache.sshd.client.channel.ClientChannelEvent;
 import org.apache.sshd.client.channel.PtyCapableChannelSession;
 import org.apache.sshd.client.future.ConnectFuture;
 import org.apache.sshd.client.session.ClientSession;
+import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.RuntimeSshException;
-import org.apache.sshd.common.SshConstants;
 import org.apache.sshd.common.channel.PtyMode;
-import org.apache.sshd.common.kex.KeyExchange;
 import org.apache.sshd.common.keyprovider.AbstractFileKeyPairProvider;
-import org.apache.sshd.common.session.Session;
 import org.apache.sshd.common.util.SecurityUtils;
-import org.apache.sshd.common.util.buffer.Buffer;
-import org.fusesource.jansi.AnsiConsole;
-import org.fusesource.jansi.internal.CLibrary;
+import org.apache.sshd.common.util.io.NoCloseInputStream;
+import org.jline.terminal.Attributes;
+import org.jline.terminal.Attributes.ControlChar;
+import org.jline.terminal.Attributes.InputFlag;
+import org.jline.terminal.Attributes.LocalFlag;
+import org.jline.terminal.Attributes.OutputFlag;
+import org.jline.terminal.Size;
+import org.jline.terminal.Terminal;
+import org.jline.terminal.TerminalBuilder;
 import org.slf4j.impl.SimpleLogger;
 
 /**
@@ -84,13 +85,10 @@ public class Main {
         if (config.getFile() != null) {
             StringBuilder sb = new StringBuilder();
             sb.setLength(0);
-            Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(config.getFile())));
-            try {
+            try (Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(config.getFile())))) {
                 for (int c = reader.read(); c >= 0; c = reader.read()) {
                     sb.append((char) c);
                 }
-            } finally {
-                reader.close();
             }
             config.setCommand(sb.toString());
         } else if (config.isBatch()) {
@@ -103,13 +101,8 @@ public class Main {
             config.setCommand(sb.toString());
         }
 
-        SshClient client = null;
-        Terminal terminal = null;
-        int exitStatus = 0;
-        try {
-            ClientBuilder clientBuilder = ClientBuilder.builder();
-
-            client = clientBuilder.build();
+        try (SshClient client = ClientBuilder.builder().build())
+        {
             setupAgent(config.getUser(), config.getKeyFile(), client);
             client.getProperties().put(FactoryManager.IDLE_TIMEOUT, String.valueOf(config.getIdleTimeout()));
             final Console console = System.console();
@@ -161,94 +154,90 @@ public class Main {
             }
             session.auth().verify();
 
-            ClientChannel channel;
-            if (config.getCommand().length() > 0) {
-                channel = session.createChannel("exec", config.getCommand() + "\n");
-                channel.setIn(new ByteArrayInputStream(new byte[0]));
-            } else {
-                TerminalFactory.registerFlavor(TerminalFactory.Flavor.UNIX, UnixTerminal.class);
-                terminal = TerminalFactory.create();
-                if (terminal instanceof UnixTerminal) {
-                    TerminalLineSettings settings = ((UnixTerminal) terminal).getSettings();
-                    settings.undef("vlnext");
-                    settings.undef("vintr");
-                }
-                channel = session.createChannel("shell");
-                ConsoleInputStream in = new ConsoleInputStream(terminal.wrapInIfNeeded(System.in));
-                new Thread(in).start();
-                channel.setIn(in);
-                if (terminal instanceof UnixTerminal) {
-                    TerminalLineSettings settings = ((UnixTerminal) terminal).getSettings();
-                    Map<PtyMode, Integer> modes = new HashMap<>();
-                    // Control chars
-                    modes.put(PtyMode.VINTR, settings.getProperty("vintr"));
-                    modes.put(PtyMode.VQUIT, settings.getProperty("vquit"));
-                    modes.put(PtyMode.VERASE, settings.getProperty("verase"));
-                    modes.put(PtyMode.VKILL, settings.getProperty("vkill"));
-                    modes.put(PtyMode.VEOF, settings.getProperty("veof"));
-                    modes.put(PtyMode.VEOL, settings.getProperty("veol"));
-                    modes.put(PtyMode.VEOL2, settings.getProperty("veol2"));
-                    modes.put(PtyMode.VSTART, settings.getProperty("vstart"));
-                    modes.put(PtyMode.VSTOP, settings.getProperty("vstop"));
-                    modes.put(PtyMode.VSUSP, settings.getProperty("vsusp"));
-                    modes.put(PtyMode.VDSUSP, settings.getProperty("vdusp"));
-                    modes.put(PtyMode.VREPRINT, settings.getProperty("vreprint"));
-                    modes.put(PtyMode.VWERASE, settings.getProperty("vwerase"));
-                    modes.put(PtyMode.VLNEXT, settings.getProperty("vlnext"));
-                    modes.put(PtyMode.VSTATUS, settings.getProperty("vstatus"));
-                    modes.put(PtyMode.VDISCARD, settings.getProperty("vdiscard"));
-                    // Input flags
-                    modes.put(PtyMode.IGNPAR, getFlag(settings, PtyMode.IGNPAR));
-                    modes.put(PtyMode.PARMRK, getFlag(settings, PtyMode.PARMRK));
-                    modes.put(PtyMode.INPCK, getFlag(settings, PtyMode.INPCK));
-                    modes.put(PtyMode.ISTRIP, getFlag(settings, PtyMode.ISTRIP));
-                    modes.put(PtyMode.INLCR, getFlag(settings, PtyMode.INLCR));
-                    modes.put(PtyMode.IGNCR, getFlag(settings, PtyMode.IGNCR));
-                    modes.put(PtyMode.ICRNL, getFlag(settings, PtyMode.ICRNL));
-                    modes.put(PtyMode.IXON, getFlag(settings, PtyMode.IXON));
-                    modes.put(PtyMode.IXANY, getFlag(settings, PtyMode.IXANY));
-                    modes.put(PtyMode.IXOFF, getFlag(settings, PtyMode.IXOFF));
-                    // Local flags
-                    modes.put(PtyMode.ISIG, getFlag(settings, PtyMode.ISIG));
-                    modes.put(PtyMode.ICANON, getFlag(settings, PtyMode.ICANON));
-                    modes.put(PtyMode.ECHO, getFlag(settings, PtyMode.ECHO));
-                    modes.put(PtyMode.ECHOE, getFlag(settings, PtyMode.ECHOE));
-                    modes.put(PtyMode.ECHOK, getFlag(settings, PtyMode.ECHOK));
-                    modes.put(PtyMode.ECHONL, getFlag(settings, PtyMode.ECHONL));
-                    modes.put(PtyMode.NOFLSH, getFlag(settings, PtyMode.NOFLSH));
-                    modes.put(PtyMode.TOSTOP, getFlag(settings, PtyMode.TOSTOP));
-                    modes.put(PtyMode.IEXTEN, getFlag(settings, PtyMode.IEXTEN));
-                    // Output flags
-                    modes.put(PtyMode.OPOST, getFlag(settings, PtyMode.OPOST));
-                    modes.put(PtyMode.OLCUC, getFlag(settings, PtyMode.OLCUC));
-                    modes.put(PtyMode.ONLCR, getFlag(settings, PtyMode.ONLCR));
-                    modes.put(PtyMode.OCRNL, getFlag(settings, PtyMode.OCRNL));
-                    modes.put(PtyMode.ONOCR, getFlag(settings, PtyMode.ONOCR));
-                    modes.put(PtyMode.ONLRET, getFlag(settings, PtyMode.ONLRET));
-                    ((ChannelShell) channel).setPtyModes(modes);
-                } else {
-                    ((ChannelShell) channel).setupSensibleDefaultPty();
-                }
-                ((ChannelShell) channel).setPtyColumns(terminal.getWidth());
-                ((ChannelShell) channel).setPtyLines(terminal.getHeight());
-                ((ChannelShell) channel).setAgentForwarding(true);
-                String ctype = System.getenv("LC_CTYPE");
-                if (ctype == null) {
-                    ctype = Locale.getDefault().toString() + "."
-                            + System.getProperty("input.encoding", Charset.defaultCharset().name());
+            int exitStatus = 0;
+            try (Terminal terminal = TerminalBuilder.terminal()) {
+                Attributes attributes = terminal.enterRawMode();
+                try {
+                    ClientChannel channel;
+                    if (config.getCommand().length() > 0) {
+                        channel = session.createChannel("exec", config.getCommand() + "\n");
+                        channel.setIn(new ByteArrayInputStream(new byte[0]));
+                    } else {
+                        ChannelShell shell = session.createShellChannel();
+                        channel = shell;
+                        channel.setIn(new NoCloseInputStream(terminal.input()));
+
+                        Map<PtyMode, Integer> modes = new HashMap<>();
+                        // Control chars
+                        modes.put(PtyMode.VINTR, attributes.getControlChar(ControlChar.VINTR));
+                        modes.put(PtyMode.VQUIT, attributes.getControlChar(ControlChar.VQUIT));
+                        modes.put(PtyMode.VERASE, attributes.getControlChar(ControlChar.VERASE));
+                        modes.put(PtyMode.VKILL, attributes.getControlChar(ControlChar.VKILL));
+                        modes.put(PtyMode.VEOF, attributes.getControlChar(ControlChar.VEOF));
+                        modes.put(PtyMode.VEOL, attributes.getControlChar(ControlChar.VEOL));
+                        modes.put(PtyMode.VEOL2, attributes.getControlChar(ControlChar.VEOL2));
+                        modes.put(PtyMode.VSTART, attributes.getControlChar(ControlChar.VSTART));
+                        modes.put(PtyMode.VSTOP, attributes.getControlChar(ControlChar.VSTOP));
+                        modes.put(PtyMode.VSUSP, attributes.getControlChar(ControlChar.VSUSP));
+                        modes.put(PtyMode.VDSUSP, attributes.getControlChar(ControlChar.VDSUSP));
+                        modes.put(PtyMode.VREPRINT, attributes.getControlChar(ControlChar.VREPRINT));
+                        modes.put(PtyMode.VWERASE, attributes.getControlChar(ControlChar.VWERASE));
+                        modes.put(PtyMode.VLNEXT, attributes.getControlChar(ControlChar.VLNEXT));
+                        modes.put(PtyMode.VSTATUS, attributes.getControlChar(ControlChar.VSTATUS));
+                        modes.put(PtyMode.VDISCARD, attributes.getControlChar(ControlChar.VDISCARD));
+                        // Input flags
+                        modes.put(PtyMode.IGNPAR, getFlag(attributes, InputFlag.IGNPAR));
+                        modes.put(PtyMode.PARMRK, getFlag(attributes, InputFlag.PARMRK));
+                        modes.put(PtyMode.INPCK, getFlag(attributes, InputFlag.INPCK));
+                        modes.put(PtyMode.ISTRIP, getFlag(attributes, InputFlag.ISTRIP));
+                        modes.put(PtyMode.INLCR, getFlag(attributes, InputFlag.INLCR));
+                        modes.put(PtyMode.IGNCR, getFlag(attributes, InputFlag.IGNCR));
+                        modes.put(PtyMode.ICRNL, getFlag(attributes, InputFlag.ICRNL));
+                        modes.put(PtyMode.IXON, getFlag(attributes, InputFlag.IXON));
+                        modes.put(PtyMode.IXANY, getFlag(attributes, InputFlag.IXANY));
+                        modes.put(PtyMode.IXOFF, getFlag(attributes, InputFlag.IXOFF));
+                        // Local flags
+                        modes.put(PtyMode.ISIG, getFlag(attributes, LocalFlag.ISIG));
+                        modes.put(PtyMode.ICANON, getFlag(attributes, LocalFlag.ICANON));
+                        modes.put(PtyMode.ECHO, getFlag(attributes, LocalFlag.ECHO));
+                        modes.put(PtyMode.ECHOE, getFlag(attributes, LocalFlag.ECHOE));
+                        modes.put(PtyMode.ECHOK, getFlag(attributes, LocalFlag.ECHOK));
+                        modes.put(PtyMode.ECHONL, getFlag(attributes, LocalFlag.ECHONL));
+                        modes.put(PtyMode.NOFLSH, getFlag(attributes, LocalFlag.NOFLSH));
+                        modes.put(PtyMode.TOSTOP, getFlag(attributes, LocalFlag.TOSTOP));
+                        modes.put(PtyMode.IEXTEN, getFlag(attributes, LocalFlag.IEXTEN));
+                        // Output flags
+                        modes.put(PtyMode.OPOST, getFlag(attributes, OutputFlag.OPOST));
+                        modes.put(PtyMode.ONLCR, getFlag(attributes, OutputFlag.ONLCR));
+                        modes.put(PtyMode.OCRNL, getFlag(attributes, OutputFlag.OCRNL));
+                        modes.put(PtyMode.ONOCR, getFlag(attributes, OutputFlag.ONOCR));
+                        modes.put(PtyMode.ONLRET, getFlag(attributes, OutputFlag.ONLRET));
+                        shell.setPtyModes(modes);
+                        shell.setPtyColumns(terminal.getWidth());
+                        shell.setPtyLines(terminal.getHeight());
+                        shell.setAgentForwarding(true);
+                        String ctype = System.getenv("LC_CTYPE");
+                        if (ctype == null) {
+                            ctype = Locale.getDefault().toString() + "."
+                                    + System.getProperty("input.encoding", Charset.defaultCharset().name());
+                        }
+                        shell.setEnv("LC_CTYPE", ctype);
+                    }
+                    channel.setOut(terminal.output());
+                    channel.setErr(terminal.output());
+                    channel.open().verify();
+                    if (channel instanceof PtyCapableChannelSession) {
+                        registerSignalHandler(terminal, (PtyCapableChannelSession) channel);
+                    }
+                    channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
+                    if (channel.getExitStatus() != null) {
+                        exitStatus = channel.getExitStatus();
+                    }
+                } finally {
+                    terminal.setAttributes(attributes);
                 }
-                ((ChannelShell) channel).setEnv("LC_CTYPE", ctype);
-            }
-            channel.setOut(AnsiConsole.wrapOutputStream(System.out));
-            channel.setErr(AnsiConsole.wrapOutputStream(System.err));
-            channel.open().verify();
-            if (channel instanceof PtyCapableChannelSession) {
-                registerSignalHandler(terminal, (PtyCapableChannelSession) channel);
-            }
-            channel.waitFor(EnumSet.of(ClientChannelEvent.CLOSED), 0);
-            if (channel.getExitStatus() != null) {
-                exitStatus = channel.getExitStatus();
             }
+            System.exit(exitStatus);
         } catch (Throwable t) {
             if (config.getLevel() > SimpleLogger.WARN) {
                 t.printStackTrace();
@@ -256,24 +245,19 @@ public class Main {
                 System.err.println(t.getMessage());
             }
             System.exit(1);
-        } finally {
-            try {
-                client.stop();
-            } catch (Throwable t) {
-            }
-            try {
-                if (terminal != null) {
-                    terminal.restore();
-                }
-            } catch (Throwable t) {
-            }
         }
-        System.exit(exitStatus);
     }
 
-    private static int getFlag(TerminalLineSettings settings, PtyMode mode) {
-        String name = mode.toString().toLowerCase();
-        return (settings.getPropertyAsString(name) != null) ? 1 : 0;
+    private static int getFlag(Attributes attributes, InputFlag flag) {
+        return attributes.getInputFlag(flag) ? 1 : 0;
+    }
+
+    private static int getFlag(Attributes attributes, OutputFlag flag) {
+        return attributes.getOutputFlag(flag) ? 1 : 0;
+    }
+
+    private static int getFlag(Attributes attributes, LocalFlag flag) {
+        return attributes.getLocalFlag(flag) ? 1 : 0;
     }
 
     private static void setupAgent(String user, String keyFile, SshClient client) {
@@ -338,24 +322,6 @@ public class Main {
         }
     }
 
-    private static String readLine(String msg) throws IOException {
-        StringBuffer sb = new StringBuffer();
-        System.err.print(msg);
-        System.err.flush();
-        for (; ; ) {
-            int c = System.in.read();
-            if (c < 0) {
-                return null;
-            }
-            System.err.print((char) c);
-            if (c == '\r' || c == '\n') {
-                break;
-            }
-            sb.append((char) c);
-        }
-        return sb.toString();
-    }
-
     private static void registerSignalHandler(final Terminal terminal, final PtyCapableChannelSession channel) {
         try {
             Class<?> signalClass = Class.forName("sun.misc.Signal");
@@ -364,36 +330,18 @@ public class Main {
             Object signalHandler = Proxy.newProxyInstance(Main.class.getClassLoader(),
                     new Class<?>[]{signalHandlerClass}, new InvocationHandler() {
                         public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                            // Ugly hack to force the jline unix terminal to retrieve the width/height of the terminal
-                            // because results are cached for 1 second.
-                            try {
-                                Field field = terminal.getClass().getSuperclass().getDeclaredField("settings");
-                                field.setAccessible(true);
-                                Object settings = field.get(terminal);
-                                field = settings.getClass().getDeclaredField("configLastFetched");
-                                field.setAccessible(true);
-                                field.setLong(settings, 0L);
-                            } catch (Throwable t) {
-                                // Ignore
-                            }
-                            // TODO: replace with PtyCapableChannelSession#sendWindowChange
-                            Session session = channel.getSession();
-                            Buffer buffer = session.createBuffer(SshConstants.SSH_MSG_CHANNEL_REQUEST);
-                            buffer.putInt(channel.getRecipient());
-                            buffer.putString("window-change");
-                            buffer.putBoolean(false);
-                            buffer.putInt(terminal.getWidth());
-                            buffer.putInt(terminal.getHeight());
-                            buffer.putInt(0);
-                            buffer.putInt(0);
-                            session.writePacket(buffer);
+                            Size size = terminal.getSize();
+                            channel.sendWindowChange(size.getColumns(), size.getRows());
                             return null;
                         }
                     }
             );
             // Register the signal handler, this code is equivalent to:
             // Signal.handle(new Signal("CONT"), signalHandler);
-            signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signalClass.getConstructor(String.class).newInstance("WINCH"), signalHandler);
+            signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(
+                    null,
+                    signalClass.getConstructor(String.class).newInstance("WINCH"),
+                    signalHandler);
         } catch (Exception e) {
             // Ignore this exception, if the above failed, the signal API is incompatible with what we're expecting
 
@@ -408,101 +356,14 @@ public class Main {
             Object signalHandler = signalHandlerClass.getField("SIG_DFL").get(null);
             // Register the signal handler, this code is equivalent to:
             // Signal.handle(new Signal("CONT"), signalHandler);
-            signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signalClass.getConstructor(String.class).newInstance("WINCH"), signalHandler);
+            signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(
+                    null,
+                    signalClass.getConstructor(String.class).newInstance("WINCH"),
+                    signalHandler);
         } catch (Exception e) {
             // Ignore this exception, if the above failed, the signal API is incompatible with what we're expecting
 
         }
     }
 
-    private static class ConsoleInputStream extends InputStream implements Runnable {
-
-        private InputStream in;
-        private boolean eof = false;
-        private final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1024);
-
-        public ConsoleInputStream(InputStream in) {
-            this.in = in;
-        }
-
-        private int read(boolean wait) throws IOException {
-            if (eof && queue.isEmpty()) {
-                return -1;
-            }
-            Integer i;
-            if (wait) {
-                try {
-                    i = queue.take();
-                } catch (InterruptedException e) {
-                    throw new InterruptedIOException();
-                }
-            } else {
-                i = queue.poll();
-            }
-            if (i == null) {
-                return -1;
-            }
-            return i;
-        }
-
-        @Override
-        public int read() throws IOException {
-            return read(true);
-        }
-
-        @Override
-        public int read(byte b[], int off, int len) throws IOException {
-            if (b == null) {
-                throw new NullPointerException();
-            } else if (off < 0 || len < 0 || len > b.length - off) {
-                throw new IndexOutOfBoundsException();
-            } else if (len == 0) {
-                return 0;
-            }
-
-            int nb = 1;
-            int i = read(true);
-            if (i < 0) {
-                return -1;
-            }
-            b[off++] = (byte) i;
-            while (nb < len) {
-                i = read(false);
-                if (i < 0) {
-                    return nb;
-                }
-                b[off++] = (byte) i;
-                nb++;
-            }
-            return nb;
-        }
-
-        @Override
-        public int available() throws IOException {
-            return queue.size();
-        }
-
-        public void run() {
-            try {
-                while (true) {
-                    try {
-                        int c = in.read();
-                        if (c == -1) {
-                            return;
-                        }
-                        queue.put(c);
-                    } catch (Throwable t) {
-                        return;
-                    }
-                }
-            } finally {
-                eof = true;
-                try {
-                    queue.put(-1);
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/demos/profiles/registry/pom.xml
----------------------------------------------------------------------
diff --git a/demos/profiles/registry/pom.xml b/demos/profiles/registry/pom.xml
index 8e55551..74e030d 100644
--- a/demos/profiles/registry/pom.xml
+++ b/demos/profiles/registry/pom.xml
@@ -34,7 +34,7 @@
 
     <properties>
         <activemq.version>5.11.1</activemq.version>
-        <camel.version>2.15.2</camel.version>
+        <camel.version>2.16.2</camel.version>
         <cxf.version>3.1.0</cxf.version>
     </properties>
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
----------------------------------------------------------------------
diff --git a/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java b/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
index e4f9854..2e71ff7 100644
--- a/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
+++ b/features/command/src/main/java/org/apache/karaf/features/command/completers/FeatureCompleterSupport.java
@@ -16,16 +16,16 @@
  */
 package org.apache.karaf.features.command.completers;
 
+import java.util.ArrayList;
 import java.util.List;
-import java.util.SortedSet;
 
 import org.apache.karaf.features.Feature;
 import org.apache.karaf.features.FeaturesService;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
+import org.apache.karaf.shell.api.console.Candidate;
 import org.apache.karaf.shell.api.console.CommandLine;
 import org.apache.karaf.shell.api.console.Completer;
 import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.support.completers.StringsCompleter;
 
 /**
  * Base completer for feature commands.
@@ -42,22 +42,33 @@ public abstract class FeatureCompleterSupport implements Completer {
         this.featuresService = featuresService;
     }
 
+    @Override
     public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
-        StringsCompleter delegate = new StringsCompleter();
+        List<Candidate> cands = new ArrayList<>();
+        completeCandidates(session, commandLine, cands);
+        for (Candidate cand : cands) {
+            candidates.add(cand.value());
+        }
+        return candidates.isEmpty() ? -1 : 0;
+    }
+
+    @Override
+    public void completeCandidates(Session session, CommandLine commandLine, List<Candidate> candidates) {
         try {
             for (Feature feature : featuresService.listFeatures()) {
                 if (acceptsFeature(feature)) {
-                    add(delegate.getStrings(), feature);
+                    add(candidates, feature);
                 }
             }
         } catch (Exception e) {
             // Ignore
         }
-        return delegate.complete(session, commandLine, candidates);
     }
 
-    protected void add(SortedSet<String> candidates, Feature feature) {
-        candidates.add(feature.getName());
+    protected void add(List<Candidate> candidates, Feature feature) {
+        candidates.add(new Candidate(
+                feature.getName(), feature.getName(), null,
+                feature.getDescription(), null, null, true));
     }
 
     /**

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
index 6372b8a..5a3c03b 100644
--- a/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
+++ b/instance/src/main/java/org/apache/karaf/instance/core/internal/InstanceServiceImpl.java
@@ -52,9 +52,9 @@ import org.apache.karaf.jpm.impl.ScriptUtils;
 import org.apache.karaf.profile.Profile;
 import org.apache.karaf.profile.ProfileBuilder;
 import org.apache.karaf.profile.ProfileService;
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
 import org.apache.karaf.util.StreamUtils;
 import org.apache.karaf.util.locks.FileLockUtils;
-import org.fusesource.jansi.Ansi;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
 import org.osgi.framework.ServiceReference;
@@ -680,10 +680,10 @@ public class InstanceServiceImpl implements InstanceService {
                     throw new IllegalStateException("Instance not stopped");
                 }
 
-                println(Ansi.ansi().a("Renaming instance ")
-                        .a(Ansi.Attribute.INTENSITY_BOLD).a(oldName).a(Ansi.Attribute.RESET)
-                        .a(" to ")
-                        .a(Ansi.Attribute.INTENSITY_BOLD).a(newName).a(Ansi.Attribute.RESET).toString());
+                println("Renaming instance "
+                        + SimpleAnsi.INTENSITY_BOLD + oldName + SimpleAnsi.INTENSITY_NORMAL
+                        + " to "
+                        + SimpleAnsi.INTENSITY_BOLD + newName + SimpleAnsi.INTENSITY_NORMAL);
                 // rename directory
                 String oldLocationPath = instance.loc;
                 File oldLocation = new File(oldLocationPath);

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/instance/src/main/java/org/apache/karaf/instance/main/Execute.java
----------------------------------------------------------------------
diff --git a/instance/src/main/java/org/apache/karaf/instance/main/Execute.java b/instance/src/main/java/org/apache/karaf/instance/main/Execute.java
index d94276a..c96e62b 100644
--- a/instance/src/main/java/org/apache/karaf/instance/main/Execute.java
+++ b/instance/src/main/java/org/apache/karaf/instance/main/Execute.java
@@ -41,7 +41,6 @@ import org.apache.karaf.instance.core.internal.InstanceServiceImpl;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Command;
 import org.apache.karaf.shell.impl.action.command.DefaultActionPreparator;
-import org.fusesource.jansi.AnsiConsole;
 
 public class Execute {
     static Class<? extends Action> x = CreateCommand.class;
@@ -87,8 +86,6 @@ public class Execute {
     private static final String PROP_KARAF_OPTS = "karaf.opts";
 
     public static void main(String[] args) throws Exception {
-        AnsiConsole.systemInstall();
-
         if (args.length == 0) {
             listCommands();
             exit(0);

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java
----------------------------------------------------------------------
diff --git a/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java b/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java
index 862cc2d..916a00c 100644
--- a/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java
+++ b/itests/src/test/java/org/apache/karaf/itests/FeatureTest.java
@@ -99,7 +99,7 @@ public class FeatureTest extends KarafTestSupport {
     public void repoAddRemoveCommandWithRegex() throws Exception {
         System.out.println(executeCommand("feature:repo-add mvn:org.apache.karaf.cellar/apache-karaf-cellar/3.0.0/xml/features"));
         assertContains("apache-karaf-cellar", executeCommand("feature:repo-list"));
-        System.out.println(executeCommand("feature:repo-remove .*apache-karaf-cellar.*"));
+        System.out.println(executeCommand("feature:repo-remove '.*apache-karaf-cellar.*'"));
         assertContainsNot("apache-karaf-cellar", executeCommand("feature:repo-list"));
     }
 
@@ -121,7 +121,7 @@ public class FeatureTest extends KarafTestSupport {
 
     @Test
     public void repoRefreshCommand() throws Exception {
-        String refreshedRepo = executeCommand("feature:repo-refresh .*pax.*");
+        String refreshedRepo = executeCommand("feature:repo-refresh '.*pax.*'");
         assertContains("pax-cdi", refreshedRepo);
         assertContains("pax-web", refreshedRepo);
     }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/main/pom.xml
----------------------------------------------------------------------
diff --git a/main/pom.xml b/main/pom.xml
index 402739b..c204582 100644
--- a/main/pom.xml
+++ b/main/pom.xml
@@ -43,7 +43,7 @@
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <scope>provided</scope>
-        </dependency>    
+        </dependency>
 
         <dependency>
             <groupId>org.ops4j.pax.tinybundles</groupId>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index c75a580..188678d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -185,7 +185,8 @@
         <felix.fileinstall.version>3.5.4</felix.fileinstall.version>
         <felix.framework.version>5.5.0-SNAPSHOT</felix.framework.version>
         <felix.framework.security.version>2.4.0</felix.framework.security.version>
-        <felix.gogo.version>0.16.2</felix.gogo.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.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>
@@ -247,10 +248,9 @@
         <hibernate42.version>4.2.15.Final</hibernate42.version>
         <hibernate43.version>4.3.6.Final</hibernate43.version>
         <hibernate.validator.version>5.2.4.Final</hibernate.validator.version>
-        <jansi.version>1.11</jansi.version>
+        <jansi.version>1.12</jansi.version>
         <javassist.version>3.9.0.GA</javassist.version>
-        <jline.version>2.14.2</jline.version>
-        <jledit.version>0.2.1</jledit.version>
+        <jline.version>3.0.0.M1</jline.version>
         <jsw.version>3.2.3</jsw.version>
         <log4j.version>1.2.17</log4j.version>
         <maven.version>2.0.9</maven.version>
@@ -1188,26 +1188,14 @@
                 <version>${log4j.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.fusesource.jansi</groupId>
+                <artifactId>jansi</artifactId>
+                <version>${jansi.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>jline</groupId>
                 <artifactId>jline</artifactId>
                 <version>${jline.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>org.fusesource.jansi</groupId>
-                        <artifactId>jansi</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>org.jledit</groupId>
-                <artifactId>core</artifactId>
-                <version>${jledit.version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>org.fusesource.jansi</groupId>
-                        <artifactId>jansi</artifactId>
-                    </exclusion>
-                </exclusions>
             </dependency>
             <dependency>
                 <groupId>org.apache.maven.artifact</groupId>
@@ -1645,12 +1633,12 @@
             <dependency>
                 <groupId>org.apache.felix</groupId>
                 <artifactId>org.apache.felix.gogo.runtime</artifactId>
-                <version>${felix.gogo.version}</version>
+                <version>${felix.gogo.runtime.version}</version>
             </dependency>
             <dependency>
                 <groupId>org.apache.felix</groupId>
-                <artifactId>org.apache.felix.gogo.commands</artifactId>
-                <version>${felix.gogo.version}</version>
+                <artifactId>org.apache.felix.gogo.jline</artifactId>
+                <version>${felix.gogo.jline.version}</version>
             </dependency>
             <dependency>
                 <groupId>org.ops4j.pax.web</groupId>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/profile/pom.xml
----------------------------------------------------------------------
diff --git a/profile/pom.xml b/profile/pom.xml
index 7979c2a..3c1f021 100644
--- a/profile/pom.xml
+++ b/profile/pom.xml
@@ -133,12 +133,6 @@
         </dependency>
 
         <dependency>
-            <groupId>org.jledit</groupId>
-            <artifactId>core</artifactId>
-            <optional>true</optional>
-        </dependency>
-
-        <dependency>
             <groupId>org.slf4j</groupId>
             <artifactId>slf4j-jdk14</artifactId>
             <scope>test</scope>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/profile/src/main/java/org/apache/karaf/profile/command/ProfileEdit.java
----------------------------------------------------------------------
diff --git a/profile/src/main/java/org/apache/karaf/profile/command/ProfileEdit.java b/profile/src/main/java/org/apache/karaf/profile/command/ProfileEdit.java
index 525ef38..84b7b66 100644
--- a/profile/src/main/java/org/apache/karaf/profile/command/ProfileEdit.java
+++ b/profile/src/main/java/org/apache/karaf/profile/command/ProfileEdit.java
@@ -26,7 +26,6 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
-import jline.TerminalSupport;
 import org.apache.karaf.profile.Profile;
 import org.apache.karaf.profile.ProfileBuilder;
 import org.apache.karaf.profile.ProfileService;
@@ -37,10 +36,6 @@ 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.Terminal;
-import org.jledit.ConsoleEditor;
-import org.jledit.ContentManager;
-import org.jledit.EditorFactory;
-import org.jledit.simple.SimpleConsoleEditor;
 import org.osgi.service.cm.Configuration;
 import org.osgi.service.cm.ConfigurationAdmin;
 import org.slf4j.Logger;
@@ -131,16 +126,8 @@ public class ProfileEdit implements Action {
     private ConfigurationAdmin configurationAdmin;
 
     @Reference
-    private EditorFactory editorFactory;
-
-    @Reference
     Terminal terminal;
 
-    public void init() {
-        // TODO: Karaf 2.4 has a bug to lookup this class, so we bind it manually - Karaf 2.4.1 should have this fixed
-        this.editorFactory.bind("simple", SimpleConsoleEditor.class);
-    }
-
     @Override
     public Object execute() throws Exception {
         if (delete) {
@@ -425,12 +412,14 @@ public class ProfileEdit implements Action {
         String id = profile.getId();
         String location = id + " " + resource;
         //Call the editor
+        /* TODO:JLINE
         ConsoleEditor editor = editorFactory.create("simple", getTerminal());
         editor.setTitle("Profile");
         editor.setOpenEnabled(false);
         editor.setContentManager(new DatastoreContentManager(profileService));
         editor.open(location, id);
         editor.start();
+        */
     }
 
     public void updatedDelimitedList(Map<String, String> map, String key, String value, String delimiter, boolean set, boolean delete, boolean append, boolean remove) {
@@ -515,8 +504,6 @@ public class ProfileEdit implements Action {
     }
 
     /**
-     * Gets the {@link jline.Terminal} from the current session.
-     */
     private jline.Terminal getTerminal() throws Exception {
         try {
             return (jline.Terminal) terminal.getClass().getMethod("getTerminal").invoke(terminal);
@@ -535,10 +522,6 @@ public class ProfileEdit implements Action {
         }
     }
 
-    private Map<String, String> getConfigurationFromBuilder(ProfileBuilder builder, String pid) {
-        return builder.getConfiguration(pid);
-    }
-
     static class DatastoreContentManager implements ContentManager {
 
         private static final Charset UTF_8 = Charset.forName("UTF-8");
@@ -549,9 +532,6 @@ public class ProfileEdit implements Action {
             this.profileService = profileService;
         }
 
-        /**
-         * Loads content from the specified location.
-         */
         @Override
         public String load(String location) throws IOException {
             try {
@@ -569,9 +549,6 @@ public class ProfileEdit implements Action {
             }
         }
 
-        /**
-         * Saves content to the specified location.
-         */
         @Override
         public boolean save(String content, String location) {
             try {
@@ -591,20 +568,20 @@ public class ProfileEdit implements Action {
             return true;
         }
 
-        /**
-         * Saves the {@link String} content to the specified location using the specified {@link java.nio.charset.Charset}.
-         */
         @Override
         public boolean save(String content, Charset charset, String location) {
             return save(content, location);
         }
 
-        /**
-         * Detect the Charset of the content in the specified location.
-         */
         @Override
         public Charset detectCharset(String location) {
             return UTF_8;
         }
     }
+        */
+
+    private Map<String, String> getConfigurationFromBuilder(ProfileBuilder builder, String pid) {
+        return builder.getConfiguration(pid);
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/commands/pom.xml
----------------------------------------------------------------------
diff --git a/shell/commands/pom.xml b/shell/commands/pom.xml
index eb2206b..8efaa85 100644
--- a/shell/commands/pom.xml
+++ b/shell/commands/pom.xml
@@ -43,10 +43,6 @@
             <artifactId>org.apache.karaf.shell.core</artifactId>
         </dependency>
         <dependency>
-            <groupId>org.jledit</groupId>
-            <artifactId>core</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.apache.karaf</groupId>
             <artifactId>org.apache.karaf.util</artifactId>
             <scope>provided</scope>
@@ -110,9 +106,6 @@
                         <Bundle-Activator>
                             org.apache.karaf.shell.commands.impl.info.Activator
                         </Bundle-Activator>
-                        <Require-Capability>
-                            osgi.service;filter:="(objectClass=org.jledit.EditorFactory)";effective:=active
-                        </Require-Capability>
                     </instructions>
                 </configuration>
             </plugin>

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/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
index c201ab0..880ae43 100644
--- 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
@@ -49,56 +49,83 @@ public class DateAction implements Action {
             }
         }
         if (format == null) {
-            System.out.println(d);
-        } else {
-            // transform Unix format to Java SimpleDateFormat (if required)
-            format = format.replaceAll("%a","EEE");
-            format = format.replaceAll("%A", "EEEEEEE");
-            format = format.replaceAll("%b", "MMM");
-            format = format.replaceAll("%B", "MMMMMMM");
-            format = format.replaceAll("%c", "MMM EEE d HH:mm:ss yyyy");
-            format = format.replaceAll("%C","yy");
-            format = format.replaceAll("%d", "dd");
-            format = format.replaceAll("%D", "MM/dd/yy");
-            format = format.replaceAll("%e", "dd");
-            format = format.replaceAll("%F", "yyyy-MM-dd");
-            format = format.replaceAll("%g", "YY");
-            format = format.replaceAll("%G", "YYYY");
-            format = format.replaceAll("%h", "MMM");
-            format = format.replaceAll("%H", "HH");
-            format = format.replaceAll("%I", "hh");
-            format = format.replaceAll("%j", "DDD");
-            format = format.replaceAll("%k", "HH");
-            format = format.replaceAll("%l", "hh");
-            format = format.replaceAll("%m", "MM");
-            format = format.replaceAll("%M", "mm");
-            format = format.replaceAll("%n", "\n");
-            format = format.replaceAll("%N", "S");
-            format = format.replaceAll("%p", "aa");
-            format = format.replaceAll("%P", "aa");
-            format = format.replaceAll("%r", "hh:mm:ss aa");
-            format = format.replaceAll("%R", "HH:mm");
-            format = format.replaceAll("%s", "S");
-            format = format.replaceAll("%S", "ss");
-            format = format.replaceAll("%t", "\t");
-            format = format.replaceAll("%T", "HH:mm:ss");
-            format = format.replaceAll("%u", "u");
-            format = format.replaceAll("%U", "w");
-            format = format.replaceAll("%V", "W");
-            format = format.replaceAll("%w", "u");
-            format = format.replaceAll("%W", "w");
-            format = format.replaceAll("%x", "MM/dd/yy");
-            format = format.replaceAll("%X", "HH:mm:ss");
-            format = format.replaceAll("%y", "yy");
-            format = format.replaceAll("%Y", "yyyy");
-            format = format.replaceAll("%z", "X");
-            format = format.replaceAll("%:z", "XXX");
-            format = format.replaceAll("%::z", "XXXX");
-            format = format.replaceAll("%:::z", "XXXX");
-            format = format.replaceAll("%Z", "z");
-            DateFormat df = new SimpleDateFormat(format);
-            System.out.println(df.format(d));
+            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/b4ae5245/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
index f310949..84feb70 100644
--- 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
@@ -16,27 +16,18 @@
  */
 package org.apache.karaf.shell.commands.impl;
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.util.UUID;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.List;
 import java.util.regex.Pattern;
 
-import jline.TerminalSupport;
 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.Terminal;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.apache.karaf.util.StreamUtils;
-import org.jledit.ConsoleEditor;
-import org.jledit.EditorFactory;
+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
@@ -44,137 +35,21 @@ 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 = false)
-    private String url;
+    @Argument(index = 0, name = "url", description = "The url of the resource to edit.", required = true, multiValued = true)
+    private List<String> urls;
 
     @Reference
-    private EditorFactory editorFactory;
+    Session session;
 
     @Reference
     Terminal terminal;
 
     @Override
     public Object execute() throws Exception {
-        URLConnection connection = null;
-        InputStream is = null;
-        OutputStream os = null;
-        String path = null;
-        boolean isLocal = true;
-        String sourceUrl = url;
-
-        // if no url format found, assume file url
-        if (!URL_PATTERN.matcher(sourceUrl).matches()) {
-            File f = new File(sourceUrl);
-            sourceUrl = "file://" + f.getAbsolutePath();
-        }
-
-        URL u = new URL(sourceUrl);
-        // if its not a file url
-        if (!u.getProtocol().equals("file")) {
-            isLocal = false;
-
-            try {
-                connection = u.openConnection();
-                is = connection.getInputStream();
-            } catch (IOException ex) {
-                System.out.println("Failed to open " + sourceUrl + " for reading.");
-                return null;
-            }
-            try {
-                os = connection.getOutputStream();
-            } catch (IOException ex) {
-                System.out.println("Failed to open " + sourceUrl + " for writing.");
-                return null;
-            }
-
-            // copy the resource to a tmp location
-            FileOutputStream fos = null;
-            try {
-                path = System.getProperty("karaf.data") + "/editor/" + UUID.randomUUID();
-                File f = new File(path);
-                if (!f.exists()) {
-                    if (!f.getParentFile().exists()) {
-                        f.getParentFile().mkdirs();
-                    }
-                }
-
-                fos = new FileOutputStream(f);
-                StreamUtils.copy(is, fos);
-            } catch (Exception ex) {
-                System.out.println("Failed to copy resource from url:" + sourceUrl + " to tmp file: " + path + "  for editing.");
-            } finally {
-                StreamUtils.close(fos);
-            }
-        } else {
-            path = u.getFile();
-        }
-
-
-        File file = new File(path);
-        if (!file.exists()) {
-            if (!file.getParentFile().exists()) {
-                file.getParentFile().mkdirs();
-            }
-        }
-
-        // call the editor
-        ConsoleEditor editor = editorFactory.create(getTerminal());
-        editor.setTitle("Karaf");
-        editor.open(file.getAbsolutePath(), url);
-        editor.setOpenEnabled(false);
-        editor.start();
-
-        // if resource is not local, copy the resource back
-        if (!isLocal) {
-            FileInputStream fis = new FileInputStream(path);
-            try {
-                StreamUtils.copy(fis, os);
-            } finally {
-                StreamUtils.close(fis);
-            }
-        }
-
-        if (is != null) {
-            StreamUtils.close(is);
-        }
-
-        if (os != null) {
-            StreamUtils.close(os);
-        }
-
+        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;
     }
-
-    /**
-     * Gets the {@link jline.Terminal} from the current session.
-     *
-     * @return
-     * @throws Exception
-     */
-    private jline.Terminal getTerminal() throws Exception {
-        try {
-            return (jline.Terminal) terminal.getClass().getMethod("getTerminal").invoke(terminal);
-        } catch (Throwable t) {
-            return new TerminalSupport(true) {
-                @Override
-                public int getWidth() {
-                    return terminal.getWidth();
-                }
-
-                @Override
-                public int getHeight() {
-                    return terminal.getHeight();
-                }
-            };
-        }
-    }
-
-    public EditorFactory getEditorFactory() {
-        return editorFactory;
-    }
-
-    public void setEditorFactory(EditorFactory editorFactory) {
-        this.editorFactory = editorFactory;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/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
index 573714e..4045cf5 100644
--- 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
@@ -31,7 +31,7 @@ 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.fusesource.jansi.Ansi;
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
 
 
 @Command(scope = "shell", name="grep", description="Prints lines matching the given pattern.", detailedDescription="classpath:grep.txt")
@@ -128,20 +128,15 @@ public class GrepAction implements Action {
                         if (!invertMatch && color != ColorOption.never) {
                             int index = matcher2.start(0);
                             String prefix = line.substring(0,index);
-                            matcher2.appendReplacement(sb, Ansi.ansi()
-                                .bg(Ansi.Color.YELLOW)
-                                .fg(Ansi.Color.BLACK)
-                                .a(matcher2.group())
-                                 .reset()
-                                .a(lastEscapeSequence(prefix))
-                                .toString());
+                            matcher2.appendReplacement(sb,
+                                    "\u001b[33;40m" + matcher2.group() + "\u001b[39;49m" + lastEscapeSequence(prefix));
                         } else {
                             matcher2.appendReplacement(sb, matcher2.group());
                         }
                         nb++;
                     }
                     matcher2.appendTail(sb);
-                    sb.append(Ansi.ansi().reset().toString());
+                    sb.append(SimpleAnsi.RESET);
                     if (!count && lineNumber) {
                         lines.add(String.format("%6d  ", lineno) + sb.toString());
                     } else {
@@ -199,7 +194,7 @@ public class GrepAction implements Action {
      * @return
      */
     private String lastEscapeSequence(String str) {
-        String escapeSequence=Ansi.ansi().reset().toString();
+        String escapeSequence = SimpleAnsi.RESET;
         String escapePattern = "(\\\u001B\\[[0-9;]*[0-9]+m)+";
         Pattern pattern =  Pattern.compile(escapePattern);
         Matcher matcher = pattern.matcher(str);

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/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
index d665a03..f4b0157 100644
--- 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
@@ -19,10 +19,10 @@ 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.console.History;
 import org.apache.karaf.shell.api.action.lifecycle.Reference;
 import org.apache.karaf.shell.api.action.lifecycle.Service;
-import org.fusesource.jansi.Ansi;
+import org.apache.karaf.shell.api.console.History;
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
 
 /**
  * History command
@@ -39,19 +39,15 @@ public class HistoryAction implements Action {
 
     @Override
     public Object execute() throws Exception {
-        if (history != null && clear) {
-            history.clear();
-        }
-        
-        if (!clear) {
-            for (int index = history.first(); index <= history.last(); index++) {
-                System.out.println(
-                    Ansi.ansi()
-                        .a("  ")
-                        .a(Ansi.Attribute.INTENSITY_BOLD).render("%3d", index).a(Ansi.Attribute.INTENSITY_BOLD_OFF)
-                        .a("  ")
-                        .a(history.get(index))
-                        .toString());
+        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/b4ae5245/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java
----------------------------------------------------------------------
diff --git a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java
index c116861..f6221e9 100644
--- a/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java
+++ b/shell/commands/src/main/java/org/apache/karaf/shell/commands/impl/InfoAction.java
@@ -41,7 +41,7 @@ import org.apache.karaf.shell.commands.info.InfoProvider;
 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;
-import org.fusesource.jansi.Ansi;
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.FrameworkUtil;
@@ -214,9 +214,9 @@ public class InfoAction implements Action {
     }
 
     void printValue(String name, int pad, String value) {
-        System.out.println(Ansi.ansi().a("  ")
-                .a(Ansi.Attribute.INTENSITY_BOLD).a(name).a(spaces(pad - name.length())).a(Ansi.Attribute.RESET)
-                .a("   ").a(value).toString());
+        System.out.println(
+                "  " + SimpleAnsi.INTENSITY_BOLD + name + SimpleAnsi.INTENSITY_NORMAL
+                        + spaces(pad - name.length()) + "   ");
     }
 
     String spaces(int nb) {


[5/6] karaf git commit: [KARAF-4570] Upgrade to JLine 3

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/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
index af7bca7..9b34b81 100644
--- 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
@@ -16,28 +16,11 @@
  */
 package org.apache.karaf.shell.commands.impl;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FilterInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.InterruptedIOException;
-import java.io.OutputStream;
-import java.io.Reader;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
+import java.nio.file.Path;
+import java.nio.file.Paths;
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.List;
-import java.util.Map;
-import java.util.Stack;
-import java.util.TreeMap;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.regex.Pattern;
 
-import jline.console.KeyMap;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Argument;
 import org.apache.karaf.shell.api.action.Command;
@@ -45,23 +28,15 @@ 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.Signal;
-import org.apache.karaf.shell.api.console.SignalListener;
-import org.apache.karaf.shell.api.console.Terminal;
-import org.apache.karaf.shell.support.ansi.AnsiSplitter;
-import org.jledit.jline.NonBlockingInputStream;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
+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, SignalListener {
-
-    private static final int ESCAPE = 27;
-    public static final int ESCAPE_TIMEOUT = 100;
-    public static final int READ_EXPIRED = -2;
-
-    private final Logger log = LoggerFactory.getLogger(getClass());
+public class LessAction implements Action {
 
     @Option(name = "-e", aliases = "--quit-at-eof")
     boolean quitAtSecondEof;
@@ -91,805 +66,38 @@ public class LessAction implements Action, SignalListener {
     int tabs = 4;
 
     @Argument(multiValued = true)
-    List<File> files;
-
-    @Reference(optional = true)
-    Terminal terminal;
+    List<String> files;
 
     @Reference
     Session session;
 
-    BufferedReader reader;
-
-    NonBlockingInputStream consoleInput;
-    Reader consoleReader;
-
-    KeyMap keys;
-
-    int firstLineInMemory = 0;
-    List<String> lines = new ArrayList<>();
-
-    int firstLineToDisplay = 0;
-    int firstColumnToDisplay = 0;
-    int offsetInLine = 0;
-
-    String message;
-    final StringBuilder buffer = new StringBuilder();
-    final StringBuilder opBuffer = new StringBuilder();
-    final Stack<Character> pushBackChar = new Stack<>();
-    Thread displayThread;
-    final AtomicBoolean redraw = new AtomicBoolean();
-
-    final Map<String, Operation> options = new TreeMap<>();
-
-    int window;
-    int halfWindow;
-
-    int nbEof;
-
-    String pattern;
-
     @Override
     public Object execute() throws Exception {
-        InputStream in;
-        if (files != null && !files.isEmpty()) {
-            message = files.get(0).toString();
-            in = new FileInputStream(files.get(0));
-        } else {
-            in = System.in;
-        }
-        reader = new BufferedReader(new InputStreamReader(new InterruptibleInputStream(in)));
-        try {
-            if (terminal == null || !isTty(System.out)) {
-                String line;
-                while ((line = reader.readLine()) != null) {
-                    System.out.println(line);
-                    checkInterrupted();
-                }
-                return null;
+        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.isEmpty()) {
+            files.add("-");
+        }
+        Path pwd = Paths.get(System.getProperty("karaf.home"));
+        for (String arg : files) {
+            if ("-".equals(arg)) {
+                sources.add(new StdInSource());
             } else {
-                boolean echo = terminal.isEchoEnabled();
-                terminal.setEchoEnabled(false);
-                terminal.addSignalListener(this, Signal.WINCH);
-                try {
-                    window = terminal.getHeight() - 1;
-                    halfWindow = window / 2;
-                    keys = new KeyMap("less", false);
-                    bindKeys(keys);
-                    consoleInput = new NonBlockingInputStream(session.getKeyboard(), true);
-                    consoleReader = new InputStreamReader(consoleInput);
-
-                    // Use alternate buffer
-                    System.out.print("\u001B[?1049h");
-                    System.out.flush();
-
-                    displayThread = new Thread() {
-                        @Override
-                        public void run() {
-                            redrawLoop();
-                        }
-                    };
-                    displayThread.start();
-                    redraw();
-                    checkInterrupted();
-
-                    options.put("-e", Operation.OPT_QUIT_AT_SECOND_EOF);
-                    options.put("--quit-at-eof", Operation.OPT_QUIT_AT_SECOND_EOF);
-                    options.put("-E", Operation.OPT_QUIT_AT_FIRST_EOF);
-                    options.put("-QUIT-AT-EOF", Operation.OPT_QUIT_AT_FIRST_EOF);
-                    options.put("-N", Operation.OPT_PRINT_LINES);
-                    options.put("--LINE-NUMBERS", Operation.OPT_PRINT_LINES);
-                    options.put("-q", Operation.OPT_QUIET);
-                    options.put("--quiet", Operation.OPT_QUIET);
-                    options.put("--silent", Operation.OPT_QUIET);
-                    options.put("-Q", Operation.OPT_VERY_QUIET);
-                    options.put("--QUIET", Operation.OPT_VERY_QUIET);
-                    options.put("--SILENT", Operation.OPT_VERY_QUIET);
-                    options.put("-S", Operation.OPT_CHOP_LONG_LINES);
-                    options.put("--chop-long-lines", Operation.OPT_CHOP_LONG_LINES);
-                    options.put("-i", Operation.OPT_IGNORE_CASE_COND);
-                    options.put("--ignore-case", Operation.OPT_IGNORE_CASE_COND);
-                    options.put("-I", Operation.OPT_IGNORE_CASE_ALWAYS);
-                    options.put("--IGNORE-CASE", Operation.OPT_IGNORE_CASE_ALWAYS);
-
-                    Operation op;
-                    do {
-                        checkInterrupted();
-
-                        op = null;
-                        //
-                        // Option edition
-                        //
-                        if (buffer.length() > 0 && buffer.charAt(0) == '-') {
-                            int c = consoleReader.read();
-                            message = null;
-                            if (buffer.length() == 1) {
-                                buffer.append((char) c);
-                                if (c != '-') {
-                                    op = options.get(buffer.toString());
-                                    if (op == null) {
-                                        message = "There is no " + printable(buffer.toString()) + " option";
-                                        buffer.setLength(0);
-                                    }
-                                }
-                            } else if (c == '\r') {
-                                op = options.get(buffer.toString());
-                                if (op == null) {
-                                    message = "There is no " + printable(buffer.toString()) + " option";
-                                    buffer.setLength(0);
-                                }
-                            } else {
-                                buffer.append((char) c);
-                                Map<String, Operation> matching = new HashMap<>();
-                                for (Map.Entry<String, Operation> entry : options.entrySet()) {
-                                    if (entry.getKey().startsWith(buffer.toString())) {
-                                        matching.put(entry.getKey(), entry.getValue());
-                                    }
-                                }
-                                switch (matching.size()) {
-                                case 0:
-                                    buffer.setLength(0);
-                                    break;
-                                case 1:
-                                    buffer.setLength(0);
-                                    buffer.append(matching.keySet().iterator().next());
-                                    break;
-                                }
-                            }
-
-                        }
-                        //
-                        // Pattern edition
-                        //
-                        else if (buffer.length() > 0 && (buffer.charAt(0) == '/' || buffer.charAt(0) == '?')) {
-                            int c = consoleReader.read();
-                            message = null;
-                            if (c == '\r') {
-                                pattern = buffer.toString().substring(1);
-                                if (buffer.charAt(0) == '/') {
-                                    moveToNextMatch();
-                                } else {
-                                    moveToPreviousMatch();
-                                }
-                                buffer.setLength(0);
-                            } else {
-                                buffer.append((char) c);
-                            }
-                        }
-                        //
-                        // Command reading
-                        //
-                        else {
-                            Object obj = readOperation();
-                            message = null;
-                            if (obj instanceof Character) {
-                                char c = (char) obj;
-                                // Enter option mode or pattern edit mode
-                                if (c == '-' || c == '/' || c == '?') {
-                                    buffer.setLength(0);
-                                }
-                                buffer.append((char) obj);
-                            } else if (obj instanceof Operation) {
-                                op = (Operation) obj;
-                            }
-                        }
-                        if (op != null) {
-                            switch (op) {
-                            case FORWARD_ONE_LINE:
-                                moveForward(getStrictPositiveNumberInBuffer(1));
-                                break;
-                            case BACKWARD_ONE_LINE:
-                                moveBackward(getStrictPositiveNumberInBuffer(1));
-                                break;
-                            case FORWARD_ONE_WINDOW_OR_LINES:
-                                moveForward(getStrictPositiveNumberInBuffer(window));
-                                break;
-                            case FORWARD_ONE_WINDOW_AND_SET:
-                                window = getStrictPositiveNumberInBuffer(window);
-                                moveForward(window);
-                                break;
-                            case FORWARD_ONE_WINDOW_NO_STOP:
-                                moveForward(window);
-                                // TODO: handle no stop
-                                break;
-                            case FORWARD_HALF_WINDOW_AND_SET:
-                                halfWindow = getStrictPositiveNumberInBuffer(halfWindow);
-                                moveForward(halfWindow);
-                                break;
-                            case BACKWARD_ONE_WINDOW_AND_SET:
-                                window = getStrictPositiveNumberInBuffer(window);
-                                moveBackward(window);
-                                break;
-                            case BACKWARD_ONE_WINDOW_OR_LINES:
-                                moveBackward(getStrictPositiveNumberInBuffer(window));
-                                break;
-                            case BACKWARD_HALF_WINDOW_AND_SET:
-                                halfWindow = getStrictPositiveNumberInBuffer(halfWindow);
-                                moveBackward(halfWindow);
-                                break;
-                            case GO_TO_FIRST_LINE_OR_N:
-                                // TODO: handle number
-                                firstLineToDisplay = firstLineInMemory;
-                                offsetInLine = 0;
-                                break;
-                            case GO_TO_LAST_LINE_OR_N:
-                                // TODO: handle number
-                                moveForward(Integer.MAX_VALUE);
-                                break;
-                            case LEFT_ONE_HALF_SCREEN:
-                                firstColumnToDisplay = Math.max(0, firstColumnToDisplay - terminal.getWidth() / 2);
-                                break;
-                            case RIGHT_ONE_HALF_SCREEN:
-                                firstColumnToDisplay += terminal.getWidth() / 2;
-                                break;
-                            case REPEAT_SEARCH_BACKWARD:
-                            case REPEAT_SEARCH_BACKWARD_SPAN_FILES:
-                                moveToPreviousMatch();
-                                break;
-                            case REPEAT_SEARCH_FORWARD:
-                            case REPEAT_SEARCH_FORWARD_SPAN_FILES:
-                                moveToNextMatch();
-                                break;
-                            case UNDO_SEARCH:
-                                pattern = null;
-                                break;
-                            case OPT_PRINT_LINES:
-                                buffer.setLength(0);
-                                printLineNumbers = !printLineNumbers;
-                                message = printLineNumbers ? "Constantly display line numbers" : "Don't use line numbers";
-                                break;
-                            case OPT_QUIET:
-                                buffer.setLength(0);
-                                quiet = !quiet;
-                                veryQuiet = false;
-                                message = quiet ? "Ring the bell for errors but not at eof/bof" : "Ring the bell for errors AND at eof/bof";
-                                break;
-                            case OPT_VERY_QUIET:
-                                buffer.setLength(0);
-                                veryQuiet = !veryQuiet;
-                                quiet = false;
-                                message = veryQuiet ? "Never ring the bell" : "Ring the bell for errors AND at eof/bof";
-                                break;
-                            case OPT_CHOP_LONG_LINES:
-                                buffer.setLength(0);
-                                offsetInLine = 0;
-                                chopLongLines = !chopLongLines;
-                                message = chopLongLines ? "Chop long lines" : "Fold long lines";
-                                break;
-                            case OPT_IGNORE_CASE_COND:
-                                ignoreCaseCond = !ignoreCaseCond;
-                                ignoreCaseAlways = false;
-                                message = ignoreCaseCond ? "Ignore case in searches" : "Case is significant in searches";
-                                break;
-                            case OPT_IGNORE_CASE_ALWAYS:
-                                ignoreCaseAlways = !ignoreCaseAlways;
-                                ignoreCaseCond = false;
-                                message = ignoreCaseAlways ? "Ignore case in searches and in patterns" : "Case is significant in searches";
-                                break;
-                            }
-                            buffer.setLength(0);
-                        }
-                        redraw();
-                        if (quitAtFirstEof && nbEof > 0 || quitAtSecondEof && nbEof > 1) {
-                            op = Operation.EXIT;
-                        }
-                    } while (op != Operation.EXIT);
-                } catch (InterruptedException ie) {
-                    log.debug("Interrupted by user");
-                } finally {
-                    terminal.setEchoEnabled(echo);
-                    terminal.removeSignalListener(this);
-                    consoleInput.shutdown();
-                    displayThread.interrupt();
-                    displayThread.join();
-                    // Use main buffer
-                    System.out.print("\u001B[?1049l");
-                    // Clear line
-                    System.out.println();
-                    System.out.flush();
-                }
+                sources.add(new URLSource(pwd.resolve(arg).toUri().toURL(), arg));
             }
-        } finally {
-            reader.close();
         }
+        less.run(sources);
         return null;
     }
 
-    private void moveToNextMatch() throws IOException {
-        Pattern compiled = getPattern();
-        if (compiled != null) {
-            for (int lineNumber = firstLineToDisplay + 1; ; lineNumber++) {
-                String line = getLine(lineNumber);
-                if (line == null) {
-                    break;
-                } else if (compiled.matcher(line).find()) {
-                    firstLineToDisplay = lineNumber;
-                    offsetInLine = 0;
-                    return;
-                }
-            }
-        }
-        message = "Pattern not found";
-    }
-
-    private void moveToPreviousMatch() throws IOException {
-        Pattern compiled = getPattern();
-        if (compiled != null) {
-            for (int lineNumber = firstLineToDisplay - 1; lineNumber >= firstLineInMemory; lineNumber--) {
-                String line = getLine(lineNumber);
-                if (line == null) {
-                    break;
-                } else if (compiled.matcher(line).find()) {
-                    firstLineToDisplay = lineNumber;
-                    offsetInLine = 0;
-                    return;
-                }
-            }
-        }
-        message = "Pattern not found";
-    }
-
-    private String printable(String s) {
-        StringBuilder sb = new StringBuilder();
-        for (int i = 0; i < s.length(); i++) {
-            char c = s.charAt(i);
-            if (c == ESCAPE) {
-                sb.append("ESC");
-            } else if (c < 32) {
-                sb.append('^').append((char) (c + '@'));
-            } else if (c < 128) {
-                sb.append(c);
-            } else {
-                sb.append('\\').append(String.format("03o"));
-            }
-        }
-        return sb.toString();
-    }
-
-    void moveForward(int lines) throws IOException {
-        int width = terminal.getWidth() - (printLineNumbers ? 8 : 0);
-        int height = terminal.getHeight();
-        while (--lines >= 0) {
-
-            int lastLineToDisplay = firstLineToDisplay;
-            if (firstColumnToDisplay > 0 || chopLongLines) {
-                lastLineToDisplay += height - 1;
-            } else {
-                int off = offsetInLine;
-                for (int l = 0; l < height - 1; l++) {
-                    String line = getLine(lastLineToDisplay);
-                    if (ansiLength(line) > off + width) {
-                        off += width;
-                    } else {
-                        off = 0;
-                        lastLineToDisplay++;
-                    }
-                }
-            }
-            if (getLine(lastLineToDisplay) == null) {
-                eof();
-                return;
-            }
-
-            String line = getLine(firstLineToDisplay);
-            if (ansiLength(line) > width + offsetInLine) {
-                offsetInLine += width;
-            } else {
-                offsetInLine = 0;
-                firstLineToDisplay++;
-            }
-        }
-    }
-
-    void moveBackward(int lines) throws IOException {
-        int width = terminal.getWidth() - (printLineNumbers ? 8 : 0);
-        while (--lines >= 0) {
-            if (offsetInLine > 0) {
-                offsetInLine = Math.max(0, offsetInLine - width);
-            } else if (firstLineInMemory < firstLineToDisplay) {
-                firstLineToDisplay--;
-                String line = getLine(firstLineToDisplay);
-                int length = ansiLength(line);
-                offsetInLine = length - length % width;
-            } else {
-                bof();
-                return;
-            }
-        }
-    }
-
-    private void eof() {
-        nbEof++;
-        message = "(END)";
-        if (!quiet && !veryQuiet && !quitAtFirstEof && !quitAtSecondEof) {
-            System.out.print((char) 0x07);
-            System.out.flush();
-        }
-    }
-
-    private void bof() {
-        if (!quiet && !veryQuiet) {
-            System.out.print((char) 0x07);
-            System.out.flush();
-        }
-    }
-
-    int getStrictPositiveNumberInBuffer(int def) {
-        try {
-            int n = Integer.parseInt(buffer.toString());
-            return (n > 0) ? n : def;
-        } catch (NumberFormatException e) {
-            return def;
-        } finally {
-            buffer.setLength(0);
-        }
-    }
-
-    void redraw() {
-        synchronized (redraw) {
-            redraw.set(true);
-            redraw.notifyAll();
-        }
-    }
-
-    void redrawLoop() {
-        synchronized (redraw) {
-            for (; ; ) {
-                try {
-                    if (redraw.compareAndSet(true, false)) {
-                        display();
-                    } else {
-                        redraw.wait();
-                    }
-                } catch (Exception e) {
-                    return;
-                }
-            }
-        }
-    }
-
-    void display() throws IOException {
-        System.out.println();
-        int width = terminal.getWidth() - (printLineNumbers ? 8 : 0);
-        int height = terminal.getHeight();
-        int inputLine = firstLineToDisplay;
-        String curLine = null;
-        Pattern compiled = getPattern();
-        for (int terminalLine = 0; terminalLine < height - 1; terminalLine++) {
-            if (curLine == null) {
-                curLine = getLine(inputLine++);
-                if (curLine == null) {
-                    curLine = "";
-                }
-                if (compiled != null) {
-                    curLine = compiled.matcher(curLine).replaceAll("\033[7m$1\033[27m");
-                }
-            }
-            String toDisplay;
-            if (firstColumnToDisplay > 0 || chopLongLines) {
-                int off = firstColumnToDisplay;
-                if (terminalLine == 0 && offsetInLine > 0) {
-                    off = Math.max(offsetInLine, off);
-                }
-                toDisplay = ansiSubstring(curLine, off, off + width);
-                curLine = null;
-            } else {
-                if (terminalLine == 0 && offsetInLine > 0) {
-                    curLine = ansiSubstring(curLine, offsetInLine, Integer.MAX_VALUE);
-                }
-                toDisplay = ansiSubstring(curLine, 0, width);
-                curLine = ansiSubstring(curLine, width, Integer.MAX_VALUE);
-                if (curLine.isEmpty()) {
-                    curLine = null;
-                }
-            }
-            if (printLineNumbers) {
-                System.out.print(String.format("%7d ", inputLine));
-            }
-            System.out.println(toDisplay);
-        }
-        System.out.flush();
-        if (message != null) {
-            System.out.print("\033[7m" + message + " \033[0m");
-        } else if (buffer.length() > 0) {
-            System.out.print(" " + buffer);
-        } else if (opBuffer.length() > 0) {
-            System.out.print(" " + printable(opBuffer.toString()));
-        } else {
-            System.out.print(":");
-        }
-        System.out.flush();
-    }
-
-    private Pattern getPattern() {
-        Pattern compiled = null;
-        if (pattern != null) {
-            boolean insensitive = ignoreCaseAlways || ignoreCaseCond && pattern.toLowerCase().equals(pattern);
-            compiled = Pattern.compile("(" + pattern + ")", insensitive ? Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE : 0);
-        }
-        return compiled;
-    }
-
-    private int ansiLength(String curLine) throws IOException {
-        return AnsiSplitter.length(curLine, tabs);
-    }
-
-    private String ansiSubstring(String curLine, int begin, int end) throws IOException {
-        return AnsiSplitter.substring(curLine, begin, end, tabs);
-    }
-
-    String getLine(int line) throws IOException {
-        while (line <= lines.size()) {
-            String str = reader.readLine();
-            if (str != null) {
-                lines.add(str);
-            } else {
-                break;
-            }
-        }
-        if (line < lines.size()) {
-            return lines.get(line);
-        }
-        return null;
-    }
-
-    @Override
-    public void signal(Signal signal) {
-        // Ugly hack to force the jline unix terminal to retrieve the width/height of the terminal
-        // because results are cached for 1 second.
-        try {
-            Field field = terminal.getClass().getDeclaredField("terminal");
-            field.setAccessible(true);
-            Object jlineTerminal = field.get(terminal);
-            field = jlineTerminal.getClass().getSuperclass().getDeclaredField("settings");
-            field.setAccessible(true);
-            Object settings = field.get(jlineTerminal);
-            field = settings.getClass().getDeclaredField("configLastFetched");
-            field.setAccessible(true);
-            field.setLong(settings, 0L);
-        } catch (Throwable t) {
-            // Ignore
-        }
-        redraw();
-    }
-
-    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();
-        }
-    }
-
-
-    protected Object readOperation() throws IOException {
-        int c = pushBackChar.isEmpty() ? consoleReader.read() : pushBackChar.pop();
-        if (c == -1) {
-            return null;
-        }
-        opBuffer.append((char) c);
-
-        Object o = keys.getBound(opBuffer);
-        if (o == jline.console.Operation.DO_LOWERCASE_VERSION) {
-            opBuffer.setLength(opBuffer.length() - 1);
-            opBuffer.append(Character.toLowerCase((char) c));
-            o = keys.getBound(opBuffer);
-        }
-
-        if (o instanceof KeyMap) {
-            if (c == ESCAPE
-                    && pushBackChar.isEmpty()
-                    && consoleInput.isNonBlockingEnabled()
-                    && consoleInput.peek(ESCAPE_TIMEOUT) == READ_EXPIRED) {
-                o = ((KeyMap) o).getAnotherKey();
-                if (o == null || o instanceof KeyMap) {
-                    return null;
-                }
-                opBuffer.setLength(0);
-            } else {
-                return null;
-            }
-        }
-
-        while (o == null && opBuffer.length() > 0) {
-            c = opBuffer.charAt(opBuffer.length() - 1);
-            opBuffer.setLength(opBuffer.length() - 1);
-            Object o2 = keys.getBound(opBuffer);
-            if (o2 instanceof KeyMap) {
-                o = ((KeyMap) o2).getAnotherKey();
-                if (o != null) {
-                    pushBackChar.push((char) c);
-                }
-            }
-        }
-
-        if (o != null) {
-            opBuffer.setLength(0);
-            pushBackChar.clear();
-        }
-        return o;
-    }
-
-
-    private void bindKeys(KeyMap map) {
-        // Arrow keys bindings
-        map.bind("\033[0A", Operation.BACKWARD_ONE_LINE);
-        map.bind("\033[0B", Operation.LEFT_ONE_HALF_SCREEN);
-        map.bind("\033[0C", Operation.RIGHT_ONE_HALF_SCREEN);
-        map.bind("\033[0D", Operation.FORWARD_ONE_LINE);
-
-        map.bind("\340\110", Operation.BACKWARD_ONE_LINE);
-        map.bind("\340\113", Operation.LEFT_ONE_HALF_SCREEN);
-        map.bind("\340\115", Operation.RIGHT_ONE_HALF_SCREEN);
-        map.bind("\340\120", Operation.FORWARD_ONE_LINE);
-        map.bind("\000\110", Operation.BACKWARD_ONE_LINE);
-        map.bind("\000\113", Operation.LEFT_ONE_HALF_SCREEN);
-        map.bind("\000\115", Operation.RIGHT_ONE_HALF_SCREEN);
-        map.bind("\000\120", Operation.FORWARD_ONE_LINE);
-
-        map.bind("\033[A", Operation.BACKWARD_ONE_LINE);
-        map.bind("\033[B", Operation.FORWARD_ONE_LINE);
-        map.bind("\033[C", Operation.RIGHT_ONE_HALF_SCREEN);
-        map.bind("\033[D", Operation.LEFT_ONE_HALF_SCREEN);
-
-        map.bind("\033[OA", Operation.BACKWARD_ONE_LINE);
-        map.bind("\033[OB", Operation.FORWARD_ONE_LINE);
-        map.bind("\033[OC", Operation.RIGHT_ONE_HALF_SCREEN);
-        map.bind("\033[OD", Operation.LEFT_ONE_HALF_SCREEN);
-
-        map.bind("\0340H", Operation.BACKWARD_ONE_LINE);
-        map.bind("\0340P", Operation.FORWARD_ONE_LINE);
-        map.bind("\0340M", Operation.RIGHT_ONE_HALF_SCREEN);
-        map.bind("\0340K", Operation.LEFT_ONE_HALF_SCREEN);
-
-        map.bind("h", Operation.HELP);
-        map.bind("H", Operation.HELP);
-
-        map.bind("q", Operation.EXIT);
-        map.bind(":q", Operation.EXIT);
-        map.bind("Q", Operation.EXIT);
-        map.bind(":Q", Operation.EXIT);
-        map.bind("ZZ", Operation.EXIT);
-
-        map.bind("e", Operation.FORWARD_ONE_LINE);
-        map.bind(ctrl('E'), Operation.FORWARD_ONE_LINE);
-        map.bind("j", Operation.FORWARD_ONE_LINE);
-        map.bind(ctrl('N'), Operation.FORWARD_ONE_LINE);
-        map.bind("\r", Operation.FORWARD_ONE_LINE);
-
-        map.bind("y", Operation.BACKWARD_ONE_LINE);
-        map.bind(ctrl('Y'), Operation.BACKWARD_ONE_LINE);
-        map.bind("k", Operation.BACKWARD_ONE_LINE);
-        map.bind(ctrl('K'), Operation.BACKWARD_ONE_LINE);
-        map.bind(ctrl('P'), Operation.BACKWARD_ONE_LINE);
-
-        map.bind("f", Operation.FORWARD_ONE_WINDOW_OR_LINES);
-        map.bind(ctrl('F'), Operation.FORWARD_ONE_WINDOW_OR_LINES);
-        map.bind(ctrl('V'), Operation.FORWARD_ONE_WINDOW_OR_LINES);
-        map.bind(" ", Operation.FORWARD_ONE_WINDOW_OR_LINES);
-
-        map.bind("b", Operation.BACKWARD_ONE_WINDOW_OR_LINES);
-        map.bind(ctrl('B'), Operation.BACKWARD_ONE_WINDOW_OR_LINES);
-        map.bind("\033v", Operation.BACKWARD_ONE_WINDOW_OR_LINES);
-
-        map.bind("z", Operation.FORWARD_ONE_WINDOW_AND_SET);
-
-        map.bind("w", Operation.BACKWARD_ONE_WINDOW_AND_SET);
-
-        map.bind("\033 ", Operation.FORWARD_ONE_WINDOW_NO_STOP);
-
-        map.bind("d", Operation.FORWARD_HALF_WINDOW_AND_SET);
-        map.bind(ctrl('D'), Operation.FORWARD_HALF_WINDOW_AND_SET);
-
-        map.bind("u", Operation.BACKWARD_HALF_WINDOW_AND_SET);
-        map.bind(ctrl('U'), Operation.BACKWARD_HALF_WINDOW_AND_SET);
-
-        map.bind("\033)", Operation.RIGHT_ONE_HALF_SCREEN);
-
-        map.bind("\033(", Operation.LEFT_ONE_HALF_SCREEN);
-
-        map.bind("F", Operation.FORWARD_FOREVER);
-
-        map.bind("n", Operation.REPEAT_SEARCH_FORWARD);
-        map.bind("N", Operation.REPEAT_SEARCH_BACKWARD);
-        map.bind("\033n", Operation.REPEAT_SEARCH_FORWARD_SPAN_FILES);
-        map.bind("\033N", Operation.REPEAT_SEARCH_BACKWARD_SPAN_FILES);
-        map.bind("\033u", Operation.UNDO_SEARCH);
-
-        map.bind("g", Operation.GO_TO_FIRST_LINE_OR_N);
-        map.bind("<", Operation.GO_TO_FIRST_LINE_OR_N);
-        map.bind("\033<", Operation.GO_TO_FIRST_LINE_OR_N);
-
-        map.bind("G", Operation.GO_TO_LAST_LINE_OR_N);
-        map.bind(">", Operation.GO_TO_LAST_LINE_OR_N);
-        map.bind("\033>", Operation.GO_TO_LAST_LINE_OR_N);
-
-        for (char c : "-/0123456789?".toCharArray()) {
-            map.bind("" + c, c);
-        }
-    }
-
-    String ctrl(char c) {
-        return "" + ((char) (c & 0x1f));
-    }
-
-    static enum Operation {
-
-        // General
-        HELP,
-        EXIT,
-
-        // Moving
-        FORWARD_ONE_LINE,
-        BACKWARD_ONE_LINE,
-        FORWARD_ONE_WINDOW_OR_LINES,
-        BACKWARD_ONE_WINDOW_OR_LINES,
-        FORWARD_ONE_WINDOW_AND_SET,
-        BACKWARD_ONE_WINDOW_AND_SET,
-        FORWARD_ONE_WINDOW_NO_STOP,
-        FORWARD_HALF_WINDOW_AND_SET,
-        BACKWARD_HALF_WINDOW_AND_SET,
-        LEFT_ONE_HALF_SCREEN,
-        RIGHT_ONE_HALF_SCREEN,
-        FORWARD_FOREVER,
-        REPAINT,
-        REPAINT_AND_DISCARD,
-
-        // Searching
-        REPEAT_SEARCH_FORWARD,
-        REPEAT_SEARCH_BACKWARD,
-        REPEAT_SEARCH_FORWARD_SPAN_FILES,
-        REPEAT_SEARCH_BACKWARD_SPAN_FILES,
-        UNDO_SEARCH,
-
-        // Jumping
-        GO_TO_FIRST_LINE_OR_N,
-        GO_TO_LAST_LINE_OR_N,
-        GO_TO_PERCENT_OR_N,
-        GO_TO_NEXT_TAG,
-        GO_TO_PREVIOUS_TAG,
-        FIND_CLOSE_BRACKET,
-        FIND_OPEN_BRACKET,
-
-        // Options
-        OPT_PRINT_LINES,
-        OPT_CHOP_LONG_LINES,
-        OPT_QUIT_AT_FIRST_EOF,
-        OPT_QUIT_AT_SECOND_EOF,
-        OPT_QUIET,
-        OPT_VERY_QUIET,
-        OPT_IGNORE_CASE_COND,
-        OPT_IGNORE_CASE_ALWAYS,
-
-    }
-
-    static class InterruptibleInputStream extends FilterInputStream {
-        InterruptibleInputStream(InputStream in) {
-            super(in);
-        }
-
-        @Override
-        public int read(byte[] b, int off, int len) throws IOException {
-            if (Thread.currentThread().isInterrupted()) {
-                throw new InterruptedIOException();
-            }
-            return super.read(b, off, len);
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/pom.xml
----------------------------------------------------------------------
diff --git a/shell/console/pom.xml b/shell/console/pom.xml
index 01d79ce..498a619 100644
--- a/shell/console/pom.xml
+++ b/shell/console/pom.xml
@@ -48,6 +48,10 @@
             <artifactId>jline</artifactId>
         </dependency>
         <dependency>
+            <groupId>org.fusesource.jansi</groupId>
+            <artifactId>jansi</artifactId>
+        </dependency>
+        <dependency>
             <groupId>org.osgi</groupId>
             <artifactId>org.osgi.core</artifactId>
             <scope>provided</scope>
@@ -145,7 +149,7 @@
                             org.apache.karaf.shell.core
                         </Fragment-Host>
                         <Import-Package>
-                            !org.apache.felix.gogo.runtime.*,
+                            !org.apache.felix.gogo.*,
                             !org.apache.karaf.shell.inject.impl,
                             org.osgi.service.event;resolution:=optional,
                             org.apache.karaf.branding;resolution:=optional,
@@ -171,9 +175,9 @@
                             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.version};-noimport:=true,
-                            org.apache.felix.service.command;version=${felix.gogo.version};-noimport:=true,
-                            org.apache.felix.service.threadio;version=${felix.gogo.version};status=provisional;mandatory:=status;-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
                         </Export-Package>
                         <Private-Package>
                         	org.apache.karaf.shell.commands.ansi,

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/commands/ansi/SimpleAnsi.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/commands/ansi/SimpleAnsi.java b/shell/console/src/main/java/org/apache/karaf/shell/commands/ansi/SimpleAnsi.java
index 0ea9ff2..7a23f4b 100644
--- a/shell/console/src/main/java/org/apache/karaf/shell/commands/ansi/SimpleAnsi.java
+++ b/shell/console/src/main/java/org/apache/karaf/shell/commands/ansi/SimpleAnsi.java
@@ -18,14 +18,11 @@
  */
 package org.apache.karaf.shell.commands.ansi;
 
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.Ansi.Color;
-
 @Deprecated
 public class SimpleAnsi {
-    public static String COLOR_RED = Ansi.ansi().fg(Color.RED).toString();
-    public static String COLOR_DEFAULT = Ansi.ansi().fg(Color.DEFAULT).toString();
-    
-    public static String INTENSITY_BOLD = Ansi.ansi().bold().toString();
-    public static String INTENSITY_NORMAL = Ansi.ansi().boldOff().toString();
+    public static String COLOR_RED = "\u001b[31m";
+    public static String COLOR_DEFAULT = "\u001b[39m";
+
+    public static String INTENSITY_BOLD = "\u001b[1m";
+    public static String INTENSITY_NORMAL = "\u001b[22m";
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/factory/ConsoleFactory.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/factory/ConsoleFactory.java b/shell/console/src/main/java/org/apache/karaf/shell/console/factory/ConsoleFactory.java
deleted file mode 100644
index 6c27434..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/factory/ConsoleFactory.java
+++ /dev/null
@@ -1,31 +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.console.factory;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-
-import jline.Terminal;
-
-import org.apache.karaf.shell.console.Console;
-
-@Deprecated
-public interface ConsoleFactory {
-    Console create(InputStream in, PrintStream out, PrintStream err, final Terminal term, String encoding, Runnable closeCallback);
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java
deleted file mode 100644
index eea5af8..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/Main.java
+++ /dev/null
@@ -1,348 +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.console.impl;
-
-import java.io.*;
-import java.lang.reflect.Method;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.List;
-
-import jline.Terminal;
-import org.apache.karaf.shell.commands.Action;
-import org.apache.karaf.shell.commands.Command;
-import org.apache.karaf.shell.commands.CommandException;
-import org.apache.karaf.shell.commands.basic.AbstractCommand;
-import org.apache.felix.gogo.runtime.CommandNotFoundException;
-import org.apache.felix.gogo.runtime.CommandProcessorImpl;
-import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.felix.service.command.Function;
-import org.apache.felix.service.threadio.ThreadIO;
-import org.apache.karaf.shell.console.NameScoping;
-import org.apache.karaf.shell.console.impl.jline.ConsoleImpl;
-import org.apache.karaf.shell.console.impl.jline.TerminalFactory;
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.AnsiConsole;
-
-public class Main {
-
-    private String application = System.getProperty("karaf.name", "root");
-    private String user = "karaf";
-
-    public static void main(String args[]) throws Exception {
-        Main main = new Main();
-        main.run(args);
-    }
-
-    /**
-     * Use this method when the shell is being executed as a top level shell.
-     *
-     * @param args The console main arguments.
-     * @throws Exception In case of console running failure.
-     */
-    public void run(String args[]) throws Exception {
-
-        ThreadIOImpl threadio = new ThreadIOImpl();
-        threadio.start();
-
-        CommandProcessorImpl commandProcessor = new CommandProcessorImpl(threadio);
-
-        InputStream in = unwrap(System.in);
-        PrintStream out = wrap(unwrap(System.out));
-        PrintStream err = wrap(unwrap(System.err));
-        run(commandProcessor, threadio, args, in, out, err);
-
-        // TODO: do we need to stop the threadio that was started?
-        // threadio.stop();
-    }
-
-    /**
-     * Use this method when the shell is being executed as a command
-     * of another shell.
-     *
-     * @param parent The parent command session.
-     * @param threadIO The thread IO to use to execute the console.
-     * @param args The console arguments.
-     * @throws Exception In case of console running failure.
-     */
-    public void run(CommandSession parent, ThreadIO threadIO, String args[]) throws Exception {
-
-        // TODO: find out what the down side of not using a real ThreadIO implementation is.
-        CommandProcessorImpl commandProcessor = new CommandProcessorImpl(new ThreadIO() {
-            public void setStreams(InputStream in, PrintStream out, PrintStream err) {
-            }
-
-            public void close() {
-            }
-        });
-
-        InputStream in = parent.getKeyboard();
-        PrintStream out = parent.getConsole();
-        PrintStream err = parent.getConsole();
-        run(commandProcessor, threadIO, args, in, out, err);
-    }
-
-    private void run(CommandProcessorImpl commandProcessor, ThreadIO threadIO, String[] args, InputStream in, PrintStream out, PrintStream err) throws Exception {
-        StringBuilder sb = new StringBuilder();
-        String classpath = null;
-        boolean batch = false;
-        String file = null;
-
-        for (int i = 0; i < args.length; i++) {
-            String arg = args[i];
-            if (arg.startsWith("--classpath=")) {
-                classpath = arg.substring("--classpath=".length());
-            } else if (arg.startsWith("-c=")) {
-                classpath = arg.substring("-c=".length());
-            } else if (arg.equals("--classpath") || arg.equals("-c")) {
-                classpath = args[++i];
-            } else if (arg.equals("-b") || arg.equals("--batch")) {
-                batch = true;
-            } else if (arg.startsWith("--file=")) {
-                file = arg.substring("--file=".length());
-            } else if (arg.startsWith("-f=")) {
-                file = arg.substring("-f=".length());
-            } else if (arg.equals("--file") || arg.equals("-f")) {
-                file = args[++i];
-            } else {
-                sb.append(arg);
-                sb.append(' ');
-            }
-        }
-
-        if (file != null) {
-            Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
-            try {
-                sb.setLength(0);
-                for (int c = reader.read(); c >= 0; c = reader.read()) {
-                    sb.append((char) c);
-                }
-            } finally {
-                reader.close();
-            }
-        } else if (batch) {
-            Reader reader = new BufferedReader(new InputStreamReader(System.in));
-            sb.setLength(0);
-            for (int c = reader.read(); c >= 0; reader.read()) {
-                sb.append((char) c);
-            }
-        }
-
-        ClassLoader cl = Main.class.getClassLoader();
-        if (classpath != null) {
-            List<URL> urls = getFiles(new File(classpath));
-            cl = new URLClassLoader(urls.toArray(new URL[urls.size()]), cl);
-        }
-
-        discoverCommands(commandProcessor, cl);
-
-        run(commandProcessor, threadIO, sb.toString(), in, out, err);
-    }
-
-    private void run(final CommandProcessorImpl commandProcessor, ThreadIO threadIO, String command, final InputStream in, final PrintStream out, final PrintStream err) throws Exception {
-
-        if (command.length() > 0) {
-
-            // Shell is directly executing a sub/command, we don't setup a terminal and console
-            // in this case, this avoids us reading from stdin un-necessarily.
-            CommandSession session = commandProcessor.createSession(in, out, err);
-            session.put("USER", user);
-            session.put("APPLICATION", application);
-            session.put(NameScoping.MULTI_SCOPE_MODE_KEY, Boolean.toString(isMultiScopeMode()));
-
-            try {
-                session.execute(command);
-            } catch (Throwable t) {
-                if (t instanceof CommandNotFoundException) {
-                    String str = Ansi.ansi()
-                            .fg(Ansi.Color.RED)
-                            .a("Command not found: ")
-                            .a(Ansi.Attribute.INTENSITY_BOLD)
-                            .a(((CommandNotFoundException) t).getCommand())
-                            .a(Ansi.Attribute.INTENSITY_BOLD_OFF)
-                            .fg(Ansi.Color.DEFAULT).toString();
-                    session.getConsole().println(str);
-                } else if (t instanceof CommandException) {
-                    session.getConsole().println(((CommandException) t).getNiceHelp());
-                } else {
-                    session.getConsole().print(Ansi.ansi().fg(Ansi.Color.RED).toString());
-                    t.printStackTrace(session.getConsole());
-                    session.getConsole().print(Ansi.ansi().fg(Ansi.Color.DEFAULT).toString());
-                }
-            }
-        } else {
-            // We are going into full blown interactive shell mode.
-
-            final TerminalFactory terminalFactory = new TerminalFactory();
-            final Terminal terminal = terminalFactory.getTerminal();
-            ConsoleImpl console = createConsole(commandProcessor, threadIO, in, out, err, terminal);
-            CommandSession session = console.getSession();
-            session.put("USER", user);
-            session.put("APPLICATION", application);
-            session.put(NameScoping.MULTI_SCOPE_MODE_KEY, Boolean.toString(isMultiScopeMode()));
-            session.put("#LINES", new Function() {
-                public Object execute(CommandSession session, List<Object> arguments) throws Exception {
-                    return Integer.toString(terminal.getHeight());
-                }
-            });
-            session.put("#COLUMNS", new Function() {
-                public Object execute(CommandSession session, List<Object> arguments) throws Exception {
-                    return Integer.toString(terminal.getWidth());
-                }
-            });
-            session.put(".jline.terminal", terminal);
-
-            console.run();
-
-            terminalFactory.destroy();
-        }
-
-    }
-
-    /**
-     * Allow sub classes of main to change the ConsoleImpl implementation used.
-     *
-     * @param commandProcessor The command processor to use.
-     * @param threadIO The thread IO to use for the console.
-     * @param in The input stream.
-     * @param out The output stream.
-     * @param err The error stream.
-     * @param terminal The terminal to use.
-     * @return The created console implementation.
-     * @throws Exception If the console creation fails.
-     */
-    protected ConsoleImpl createConsole(CommandProcessorImpl commandProcessor, ThreadIO threadIO, InputStream in, PrintStream out, PrintStream err, Terminal terminal) throws Exception {
-        return new ConsoleImpl(commandProcessor, threadIO, in, out, err, terminal, null, null, null, false);
-    }
-
-    /**
-     * Sub classes can override so that their registered commands do not conflict with the default shell
-     * implementation.
-     *
-     * @return The location of the commands resource.
-     */
-    public String getDiscoveryResource() {
-        return "META-INF/services/org/apache/karaf/shell/commands";
-    }
-
-    private void discoverCommands(CommandProcessorImpl commandProcessor, ClassLoader cl) throws IOException, ClassNotFoundException {
-        Enumeration<URL> urls = cl.getResources(getDiscoveryResource());
-        while (urls.hasMoreElements()) {
-            URL url = urls.nextElement();
-            BufferedReader r = new BufferedReader(new InputStreamReader(url.openStream()));
-            String line = r.readLine();
-            while (line != null) {
-                line = line.trim();
-                if (line.length() > 0 && line.charAt(0) != '#') {
-                    final Class<Action> actionClass = (Class<Action>) cl.loadClass(line);
-                    Command cmd = actionClass.getAnnotation(Command.class);
-                    Function function = new AbstractCommand() {
-                        @Override
-                        public Action createNewAction() {
-                            try {
-                                return ((Class<? extends Action>) actionClass).newInstance();
-                            } catch (InstantiationException e) {
-                                throw new RuntimeException(e);
-                            } catch (IllegalAccessException e) {
-                                throw new RuntimeException(e);
-                            }
-                        }
-                    };
-                    addCommand(cmd, function, commandProcessor);
-                }
-                line = r.readLine();
-            }
-            r.close();
-        }
-    }
-
-    protected void addCommand(Command cmd, Function function, CommandProcessorImpl commandProcessor) {
-        try {
-            commandProcessor.addCommand(cmd.scope(), function, cmd.name());
-        } catch (Exception e) {
-        }
-    }
-
-
-    public String getApplication() {
-        return application;
-    }
-
-    public void setApplication(String application) {
-        this.application = application;
-    }
-
-    public String getUser() {
-        return user;
-    }
-
-    public void setUser(String user) {
-        this.user = user;
-    }
-
-    /**
-     * <p>Returns whether or not we are in multi-scope mode.</p>
-     *
-     * <p>The default mode is multi-scoped where we prefix commands by their scope. If we are in single
-     * scoped mode then we don't use scope prefixes when registering or tab completing commands.</p>
-     *
-     * @return True if the command is multi-scoped, false else.
-     */
-    public boolean isMultiScopeMode() {
-        return true;
-    }
-
-    private static PrintStream wrap(PrintStream stream) {
-        OutputStream o = AnsiConsole.wrapOutputStream(stream);
-        if (o instanceof PrintStream) {
-            return ((PrintStream) o);
-        } else {
-            return new PrintStream(o);
-        }
-    }
-
-    private static <T> T unwrap(T stream) {
-        try {
-            Method mth = stream.getClass().getMethod("getRoot");
-            return (T) mth.invoke(stream);
-        } catch (Throwable t) {
-            return stream;
-        }
-    }
-
-    private static List<URL> getFiles(File base) throws MalformedURLException {
-        List<URL> urls = new ArrayList<URL>();
-        getFiles(base, urls);
-        return urls;
-    }
-
-    private static void getFiles(File base, List<URL> urls) throws MalformedURLException {
-        for (File f : base.listFiles()) {
-            if (f.isDirectory()) {
-                getFiles(f, urls);
-            } else if (f.getName().endsWith(".jar")) {
-                urls.add(f.toURI().toURL());
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/Branding.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/Branding.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/Branding.java
deleted file mode 100644
index 55148d6..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/Branding.java
+++ /dev/null
@@ -1,93 +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.console.impl.jline;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Properties;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import jline.Terminal;
-
-public final class Branding {
-    
-    static final Logger LOGGER = LoggerFactory.getLogger(Branding.class);
-    
-    private Branding() { }
-
-    public static Properties loadBrandingProperties() {
-        Properties props = new Properties();
-        loadProps(props, "org/apache/karaf/shell/console/branding.properties");
-        loadProps(props, "org/apache/karaf/branding/branding.properties");
-        return props;
-    }
-
-    public static Properties loadBrandingProperties(Terminal terminal) {
-        Properties props = new Properties();
-        if (terminal != null && terminal.getClass().getName().endsWith("SshTerminal")) {
-            //it's a ssh client, so load branding separately
-            loadProps(props, "org/apache/karaf/shell/console/branding-ssh.properties");
-        } else {
-            loadProps(props, "org/apache/karaf/shell/console/branding.properties");
-        }
-
-        loadProps(props, "org/apache/karaf/branding/branding.properties");
-        
-        // load branding from etc/branding.properties
-        File etcBranding = new File(System.getProperty("karaf.etc"), "branding.properties");
-        if (etcBranding.exists()) {
-            FileInputStream etcBrandingIs = null;
-            try {
-                etcBrandingIs = new FileInputStream(etcBranding);
-            } catch (FileNotFoundException e) {
-                LOGGER.trace("Could not load branding.", e);
-            }
-            loadProps(props, etcBrandingIs);
-        }
-        return props;
-    }
-    
-    protected static void loadProps(Properties props, String resource) {
-        InputStream is = Branding.class.getClassLoader().getResourceAsStream(resource);
-        loadProps(props, is);
-    }
-
-    protected static void loadProps(Properties props, InputStream is) {
-        try {
-            if (is != null) {
-                props.load(is);
-            }
-        } catch (IOException e) {
-            // ignore
-        } finally {
-            if (is != null) {
-                try {
-                    is.close();
-                } catch (IOException e) {
-                    // Ignore
-                }
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/CompleterAsCompletor.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/CompleterAsCompletor.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/CompleterAsCompletor.java
deleted file mode 100644
index 9c49746..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/CompleterAsCompletor.java
+++ /dev/null
@@ -1,34 +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.console.impl.jline;
-
-import java.util.List;
-
-public class CompleterAsCompletor implements jline.console.completer.Completer {
-
-    private final org.apache.karaf.shell.console.Completer completer;
-
-    public CompleterAsCompletor(org.apache.karaf.shell.console.Completer completer) {
-        this.completer = completer;
-    }
-
-    public int complete(String buffer, int cursor, List candidates) {
-        return completer.complete(buffer, cursor, candidates);
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java
deleted file mode 100644
index 02661ea..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleFactoryService.java
+++ /dev/null
@@ -1,98 +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.console.impl.jline;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.lang.management.ManagementFactory;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Properties;
-
-import jline.Terminal;
-import org.apache.felix.service.command.CommandProcessor;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.felix.service.command.Function;
-import org.apache.felix.service.threadio.ThreadIO;
-import org.apache.karaf.shell.console.Console;
-import org.apache.karaf.shell.console.factory.ConsoleFactory;
-import org.apache.karaf.shell.util.ShellUtil;
-import org.apache.karaf.util.jaas.JaasHelper;
-import org.osgi.framework.BundleContext;
-
-public class ConsoleFactoryService implements ConsoleFactory {
-
-    private static final Class<?>[] SECURITY_BUGFIX = {
-            JaasHelper.class,
-            JaasHelper.OsgiSubjectDomainCombiner.class,
-            JaasHelper.DelegatingProtectionDomain.class,
-    };
-
-    private final BundleContext bundleContext;
-
-    private CommandProcessor processor;
-
-    private ThreadIO threadIO;
-
-    public ConsoleFactoryService(BundleContext bc, CommandProcessor processor, ThreadIO threadIO) {
-        bundleContext = bc;
-        this.processor = processor;
-        this.threadIO = threadIO;
-    }
-    
-    @Override
-    public Console create(InputStream in, PrintStream out, PrintStream err, final Terminal terminal,
-            String encoding, Runnable closeCallback) {
-        ConsoleImpl console = new ConsoleImpl(processor, threadIO, in, out, err, terminal, encoding, closeCallback, bundleContext, true);
-        CommandSession session = console.getSession();
-        
-        session.put("USER", ShellUtil.getCurrentUserName());
-        session.put("APPLICATION", System.getProperty("karaf.name", "root"));
-        session.put("#LINES", new Function() {
-            public Object execute(CommandSession session, List<Object> arguments) throws Exception {
-                return Integer.toString(terminal.getHeight());
-            }
-        });
-        session.put("#COLUMNS", new Function() {
-            public Object execute(CommandSession session, List<Object> arguments) throws Exception {
-                return Integer.toString(terminal.getWidth());
-            }
-        });
-        session.put(".jline.terminal", terminal);
-        addSystemProperties(session);
-        session.put("pid", getPid());
-        return console;
-    }
-
-    private String getPid() {
-    	String name = ManagementFactory.getRuntimeMXBean().getName();
-    	String[] parts = name.split("@");
-		return parts[0];
-	}
-
-	private void addSystemProperties(CommandSession session) {
-        Properties sysProps = System.getProperties();
-        Iterator<Object> it = sysProps.keySet().iterator();
-        while (it.hasNext()) {
-            String key = (String) it.next();
-            session.put(key, System.getProperty(key));
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java
deleted file mode 100644
index 78d7479..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/ConsoleImpl.java
+++ /dev/null
@@ -1,599 +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.console.impl.jline;
-
-import java.io.CharArrayWriter;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.InterruptedIOException;
-import java.io.PrintStream;
-import java.io.Reader;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import jline.Terminal;
-import jline.UnsupportedTerminal;
-import jline.console.ConsoleReader;
-import jline.console.history.MemoryHistory;
-import jline.console.history.PersistentHistory;
-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.threadio.ThreadIO;
-import org.apache.karaf.shell.console.CloseShellException;
-import org.apache.karaf.shell.console.CommandSessionHolder;
-import org.apache.karaf.shell.console.Completer;
-import org.apache.karaf.shell.console.Console;
-import org.apache.karaf.shell.console.SessionProperties;
-import org.apache.karaf.shell.console.completer.CommandsCompleter;
-import org.apache.karaf.shell.security.impl.SecuredCommandProcessorImpl;
-import org.apache.karaf.shell.util.ShellUtil;
-import org.osgi.framework.BundleContext;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class ConsoleImpl implements Console {
-
-    public static final String SHELL_INIT_SCRIPT = "karaf.shell.init.script";
-    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})> ";
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(Console.class);
-
-    protected CommandSession session;
-    protected ThreadIO threadIO;
-    private ConsoleReader reader;
-    private BlockingQueue<Integer> queue;
-    private boolean interrupt;
-    private Thread pipe;
-    volatile private boolean running;
-    volatile private boolean eof;
-    private Runnable closeCallback;
-    private Terminal terminal;
-    private InputStream consoleInput;
-    private InputStream in;
-    private PrintStream out;
-    private PrintStream err;
-    private boolean secured;
-    private Thread thread;
-    private final BundleContext bundleContext;
-    private CommandsCompleter completer;
-
-    public ConsoleImpl(CommandProcessor processor,
-                       ThreadIO threadIO,
-                       InputStream in,
-                       PrintStream out,
-                       PrintStream err,
-                       Terminal term,
-                       String encoding,
-                       Runnable closeCallback,
-                       BundleContext bc,
-                       boolean secured) {
-        this.threadIO = threadIO;
-        this.in = in;
-        this.out = out;
-        this.err = err;
-        this.secured = secured;
-        this.queue = new ArrayBlockingQueue<Integer>(1024);
-        this.terminal = term == null ? new UnsupportedTerminal() : term;
-        this.consoleInput = new ConsoleInputStream();
-        if (secured) {
-            this.session = new DelegateSession();
-        } else {
-            this.session = processor.createSession(consoleInput, out, err);
-        }
-        this.session.put("SCOPE", "shell:bundle:*");
-        this.session.put("SUBSHELL", "");
-        this.setCompletionMode();
-        this.closeCallback = closeCallback;
-        this.bundleContext = bc;
-
-        try {
-            reader = new ConsoleReader(null,
-                    this.consoleInput,
-                    this.out,
-                    this.terminal,
-                    encoding);
-        } catch (IOException e) {
-            throw new RuntimeException("Error opening console reader", e);
-        }
-
-        final File file = getHistoryFile();
-
-        try {
-            file.getParentFile().mkdirs();
-            reader.setHistory(new KarafFileHistory(file));
-        } catch (Exception e) {
-            LOGGER.error("Can not read history from file " + file + ". Using in memory history", e);
-        }
-        
-        if (reader != null && reader.getHistory() instanceof MemoryHistory) {
-            String maxSizeStr = System.getProperty(SHELL_HISTORY_MAXSIZE);
-            if (maxSizeStr != null) {
-                ((MemoryHistory)reader.getHistory()).setMaxSize(Integer.parseInt(maxSizeStr));   
-            }
-        }
-
-        session.put(".jline.reader", reader);
-        session.put(".jline.history", reader.getHistory());
-        completer = createCompleter();
-        if (completer != null) {
-            reader.addCompleter(new CompleterAsCompletor(completer));
-        }
-        pipe = new Thread(new Pipe());
-        pipe.setName("gogo shell pipe thread");
-        pipe.setDaemon(true);
-    }
-
-    /**
-     * Subclasses can override to use a different history file.
-     *
-     * @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));
-    }
-
-    public boolean isSecured() {
-        return secured;
-    }
-
-    public CommandSession getSession() {
-        return session;
-    }
-
-    public void close(boolean closedByUser) {
-        if (!running) {
-            return;
-        }
-        if (reader.getHistory() instanceof PersistentHistory) {
-            try {
-                ((PersistentHistory) reader.getHistory()).flush();
-            } catch (IOException e) {
-                // ignore
-            }
-        }
-        running = false;
-        CommandSessionHolder.unset();
-        pipe.interrupt();
-        completer.dispose();
-        if (closedByUser && closeCallback != null) {
-            closeCallback.run();
-        }
-    }
-
-    public void run() {
-        try {
-            threadIO.setStreams(consoleInput, out, err);
-            SecuredCommandProcessorImpl secCP = null;
-            if (secured) {
-                secCP = createSecuredCommandProcessor();
-            }
-            thread = Thread.currentThread();
-            CommandSessionHolder.setSession(session);
-            running = true;
-            pipe.start();
-            Properties brandingProps = Branding.loadBrandingProperties(terminal);
-            welcome(brandingProps);
-            setSessionProperties(brandingProps);
-            String scriptFileName = System.getProperty(SHELL_INIT_SCRIPT);
-            executeScript(scriptFileName);
-            while (running) {
-                try {
-                    String command = readAndParseCommand();
-                    if (command == null) {
-                        break;
-                    }
-                    //session.getConsole().println("Executing: " + line);
-                    Object result = session.execute(command);
-                    if (result != null) {
-                        session.getConsole().println(session.format(result, Converter.INSPECT));
-                    }
-                } catch (InterruptedIOException e) {
-                    //System.err.println("^C");
-                    // TODO: interrupt current thread
-                } catch (InterruptedException e) {
-                    //interrupt current thread
-                } catch (CloseShellException e) {
-                    break;
-                } catch (Throwable t) {
-                    ShellUtil.logException(session, t);
-                }
-            }
-            if (secured) {
-                try {
-                    secCP.close();
-                } catch (Throwable t) {
-                    // Ignore
-                }
-            }
-            close(true);
-        } finally {
-            try {
-                threadIO.close();
-            } catch (Throwable t) {
-                // Ignore
-            }
-        }
-    }
-
-    SecuredCommandProcessorImpl createSecuredCommandProcessor() {
-        if (!(session instanceof DelegateSession)) {
-            throw new IllegalStateException("Should be an Delegate Session here, about to set the delegate");
-        }
-        DelegateSession is = (DelegateSession) session;
-
-        // make it active
-        SecuredCommandProcessorImpl secCP = new SecuredCommandProcessorImpl(bundleContext);
-        CommandSession s = secCP.createSession(consoleInput, out, err);
-
-        // before the session is activated attributes may have been set on it. Pass these on to the real session now
-        is.setDelegate(s);
-        return secCP;
-    }
-
-    private void setCompletionMode() {
-        try {
-            File shellCfg = new File(System.getProperty("karaf.etc"), "/org.apache.karaf.shell.cfg");
-            Properties properties = new Properties();
-            properties.load(new FileInputStream(shellCfg));
-            if (properties.get("completionMode") != null) {
-                this.session.put(SessionProperties.COMPLETION_MODE, properties.get("completionMode"));
-            } else {
-                LOGGER.debug("completionMode property is not defined in etc/org.apache.karaf.shell.cfg file. Using default completion mode.");
-            }
-        } catch (Exception e) {
-            LOGGER.warn("Can't read {}/org.apache.karaf.shell.cfg file. The completion is set to default.", System.getProperty("karaf.etc"));
-        }
-    }
-
-    private String readAndParseCommand() throws IOException {
-        String command = null;
-        boolean loop = true;
-        boolean first = true;
-        while (loop) {
-            checkInterrupt();
-            String line = reader.readLine(first ? getPrompt() : "> ");
-            if (line == null) {
-                break;
-            }
-            if (command == null) {
-                command = line;
-            } else {
-                if (command.charAt(command.length() - 1) == '\\') {
-                    command = command.substring(0, command.length() - 1) + line;
-                } else {
-                    command += "\n" + line;
-                }
-            }
-            if (reader.getHistory().size() == 0) {
-                reader.getHistory().add(command);
-            } else {
-                // jline doesn't add blank lines to the history so we don't
-                // need to replace the command in jline's console history with
-                // an indented one
-                if (command.length() > 0 && !" ".equals(command)) {
-                    reader.getHistory().replace(command);
-                }
-            }
-            if (command.length() > 0 && command.charAt(command.length() - 1) == '\\') {
-                loop = true;
-                first = false;
-            } else {
-                try {
-                    Class<?> cl = CommandSession.class.getClassLoader().loadClass("org.apache.felix.gogo.runtime.Parser");
-                    Object parser = cl.getConstructor(CharSequence.class).newInstance(command);
-                    cl.getMethod("program").invoke(parser);
-                    loop = false;
-                } catch (Exception e) {
-                    loop = true;
-                    first = false;
-                } catch (Throwable t) {
-                    // Reflection problem ? just quit
-                    loop = false;
-                }
-            }
-        }
-        return command;
-    }
-
-    private void executeScript(String scriptFileName) {
-        if (scriptFileName != null) {
-            Reader r = null;
-            try {
-                File scriptFile = new File(scriptFileName);
-                r = new InputStreamReader(new FileInputStream(scriptFile));
-                CharArrayWriter w = new CharArrayWriter();
-                int n;
-                char[] buf = new char[8192];
-                while ((n = r.read(buf)) > 0) {
-                    w.write(buf, 0, n);
-                }
-                session.execute(new String(w.toCharArray()));
-            } catch (Exception e) {
-                LOGGER.debug("Error in initialization script", e);
-                System.err.println("Error in initialization script: " + e.getMessage());
-            } finally {
-                if (r != null) {
-                    try {
-                        r.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
-            }
-        }
-    }
-
-    protected void welcome(Properties brandingProps) {
-        String welcome = brandingProps.getProperty("welcome");
-        if (welcome != null && welcome.length() > 0) {
-            session.getConsole().println(welcome);
-        }
-    }
-
-    protected void setSessionProperties(Properties brandingProps) {
-        for (Map.Entry<Object, Object> entry : brandingProps.entrySet()) {
-            String key = (String) entry.getKey();
-            if (key.startsWith("session.")) {
-                session.put(key.substring("session.".length()), entry.getValue());
-            }
-        }
-    }
-
-    protected CommandsCompleter createCompleter() {
-        return new CommandsCompleter(session);
-    }
-
-    protected String getPrompt() {
-        try {
-            String prompt;
-            try {
-                Object p = session.get(PROMPT);
-                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);
-                    } else {
-                        prompt = DEFAULT_PROMPT;
-                    }
-                }
-            } catch (Throwable t) {
-                prompt = DEFAULT_PROMPT;
-            }
-            Matcher matcher = Pattern.compile("\\$\\{([^}]+)\\}").matcher(prompt);
-            while (matcher.find()) {
-                Object rep = session.get(matcher.group(1));
-                if (rep != null) {
-                    prompt = prompt.replace(matcher.group(0), rep.toString());
-                    matcher.reset(prompt);
-                }
-            }
-            return prompt;
-        } catch (Throwable t) {
-            return "$ ";
-        }
-    }
-
-    private void checkInterrupt() throws IOException {
-        if (Thread.interrupted() || interrupt) {
-            interrupt = false;
-            throw new InterruptedIOException("Keyboard interruption");
-        }
-    }
-
-    private void interrupt() {
-        interrupt = true;
-        thread.interrupt();
-    }
-
-    private class ConsoleInputStream extends InputStream {
-        private int read(boolean wait) throws IOException {
-            if (!running) {
-                return -1;
-            }
-            checkInterrupt();
-            if (eof && queue.isEmpty()) {
-                return -1;
-            }
-            Integer i;
-            if (wait) {
-                try {
-                    i = queue.take();
-                } catch (InterruptedException e) {
-                    throw new InterruptedIOException();
-                }
-                checkInterrupt();
-            } else {
-                i = queue.poll();
-            }
-            if (i == null) {
-                return -1;
-            }
-            return i;
-        }
-
-        @Override
-        public int read() throws IOException {
-            return read(true);
-        }
-
-        @Override
-        public int read(byte b[], int off, int len) throws IOException {
-            if (b == null) {
-                throw new NullPointerException();
-            } else if (off < 0 || len < 0 || len > b.length - off) {
-                throw new IndexOutOfBoundsException();
-            } else if (len == 0) {
-                return 0;
-            }
-
-            int nb = 1;
-            int i = read(true);
-            if (i < 0) {
-                return -1;
-            }
-            b[off++] = (byte) i;
-            while (nb < len) {
-                i = read(false);
-                if (i < 0) {
-                    return nb;
-                }
-                b[off++] = (byte) i;
-                nb++;
-            }
-            return nb;
-        }
-
-        @Override
-        public int available() throws IOException {
-            return queue.size();
-        }
-    }
-
-    private class Pipe implements Runnable {
-        public void run() {
-            try {
-                while (running) {
-                    try {
-                        int c = in.read();
-                        if (c == -1) {
-                            return;
-                        } else if (c == 4 && !ShellUtil.getBoolean(session, SessionProperties.IGNORE_INTERRUPTS)) {
-                            err.println("^D");
-                            interrupt();
-                            return;
-                        } else if (c == 3 && !ShellUtil.getBoolean(session, SessionProperties.IGNORE_INTERRUPTS)) {
-                            err.println("^C");
-                            reader.getCursorBuffer().clear();
-                            interrupt();
-                        }
-                        queue.put(c);
-                    } catch (Throwable t) {
-                        return;
-                    }
-                }
-            } finally {
-                eof = true;
-                try {
-                    queue.put(-1);
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-    }
-
-    static class DelegateSession implements CommandSession {
-        final Map<String, Object> attrs = new HashMap<String, Object>();
-        volatile CommandSession delegate;
-
-        @Override
-        public Object execute(CharSequence commandline) throws Exception {
-            if (delegate != null)
-                return delegate.execute(commandline);
-
-            throw new UnsupportedOperationException();
-        }
-
-        void setDelegate(CommandSession s) {
-            synchronized (this) {
-                for (Map.Entry<String, Object> entry : attrs.entrySet()) {
-                    s.put(entry.getKey(), entry.getValue());
-                }
-            }
-            delegate = s;
-        }
-
-        @Override
-        public void close() {
-            if (delegate != null)
-                delegate.close();
-        }
-
-        @Override
-        public InputStream getKeyboard() {
-            if (delegate != null)
-                return delegate.getKeyboard();
-
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public PrintStream getConsole() {
-            if (delegate != null)
-                return delegate.getConsole();
-
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Object get(String name) {
-            if (delegate != null)
-                return delegate.get(name);
-
-            return attrs.get(name);
-        }
-
-        // you can put attributes on this session before it's delegate is set...
-        @Override
-        public void put(String name, Object value) {
-            if (delegate != null) {
-                delegate.put(name, value);
-                return;
-            }
-
-            // there is no delegate yet, so we'll keep the attributes locally
-            synchronized (this) {
-                attrs.put(name, value);
-            }
-        }
-
-        @Override
-        public CharSequence format(Object target, int level) {
-            if (delegate != null)
-                return delegate.format(target, level);
-
-            throw new UnsupportedOperationException();
-        }
-
-        @Override
-        public Object convert(Class<?> type, Object instance) {
-            if (delegate != null)
-                return delegate.convert(type, instance);
-
-            throw new UnsupportedOperationException();
-        }
-    }
-
-}


[3/6] karaf git commit: [KARAF-4570] Upgrade to JLine 3

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java b/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
deleted file mode 100644
index 351a89f..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandProcessorImplTest.java
+++ /dev/null
@@ -1,142 +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.security.impl;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-
-import java.security.PrivilegedAction;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.security.auth.Subject;
-
-import org.apache.felix.gogo.api.CommandSessionListener;
-import org.apache.felix.service.command.CommandProcessor;
-import org.apache.felix.service.command.Converter;
-import org.apache.felix.service.threadio.ThreadIO;
-import org.apache.karaf.jaas.boot.principal.RolePrincipal;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.InvalidSyntaxException;
-import org.osgi.framework.ServiceEvent;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-
-public class SecuredCommandProcessorImplTest {
-    @Test
-    public void testCommandProcessor() throws Exception {
-        ThreadIO tio = EasyMock.createMock(ThreadIO.class);
-        EasyMock.replay(tio);
-
-        @SuppressWarnings("unchecked")
-        ServiceReference<ThreadIO> tioRef = EasyMock.createMock(ServiceReference.class);
-        EasyMock.replay(tioRef);
-
-        final BundleContext bc = EasyMock.createMock(BundleContext.class);
-        EasyMock.expect(bc.getServiceReference(ThreadIO.class)).andReturn(tioRef).anyTimes();
-        EasyMock.expect(bc.getService(tioRef)).andReturn(tio).anyTimes();
-        EasyMock.expect(bc.createFilter(EasyMock.isA(String.class))).andAnswer(new IAnswer<Filter>() {
-            @Override
-            public Filter answer() throws Throwable {
-                return FrameworkUtil.createFilter((String) EasyMock.getCurrentArguments()[0]);
-            }
-        }).anyTimes();
-        EasyMock.expect(bc.getServiceReferences((String) EasyMock.anyObject(), (String) EasyMock.anyObject())).andReturn(null).anyTimes();
-
-        // Capture the listeners
-        final Map<String, ServiceListener> listeners = new HashMap<String, ServiceListener>();
-
-        // Here are the expected calls
-        final String commandFilter = "(&(osgi.command.scope=*)(osgi.command.function=*)" +
-                "(|(org.apache.karaf.service.guard.roles=aaabbbccc)(!(org.apache.karaf.service.guard.roles=*))))";
-        expectServiceTracker(bc, commandFilter, listeners);
-        expectServiceTracker(bc, "(objectClass=" + Converter.class.getName() + ")", listeners);
-        expectServiceTracker(bc, "(objectClass=" + CommandSessionListener.class.getName() + ")", listeners);
-        EasyMock.replay(bc);
-
-        Subject subject = new Subject();
-        subject.getPrincipals().add(new RolePrincipal("aaabbbccc"));
-
-        Subject.doAs(subject, new PrivilegedAction<Object>() {
-            @Override
-            public Object run() {
-                MySecuredCommandProcessorImpl scp = new MySecuredCommandProcessorImpl(bc) {};
-
-                assertEquals(3, scp.getCommands().size());
-                assertTrue(scp.getCommands().contains("osgi:addcommand"));
-                assertTrue(scp.getCommands().contains("osgi:removecommand"));
-                assertTrue(scp.getCommands().contains("osgi:eval"));
-                assertEquals(1, scp.getConstants().size());
-                assertEquals(bc, scp.getConstants().get(".context"));
-
-                // Now let's make a command appear...
-                ServiceListener commandListener = listeners.get(commandFilter);
-
-                ServiceReference<?> cdRef = EasyMock.createMock(ServiceReference.class);
-                EasyMock.expect(cdRef.getProperty(CommandProcessor.COMMAND_SCOPE)).andReturn("foo");
-                EasyMock.expect(cdRef.getProperty(CommandProcessor.COMMAND_FUNCTION)).andReturn("bar");
-                EasyMock.replay(cdRef);
-
-                ServiceEvent event = new ServiceEvent(ServiceEvent.REGISTERED, cdRef);
-                commandListener.serviceChanged(event);
-                assertEquals(4, scp.getCommands().size());
-                assertTrue(scp.getCommands().contains("foo:bar"));
-
-                ServiceReference<?> cd2Ref = EasyMock.createMock(ServiceReference.class);
-                EasyMock.expect(cd2Ref.getProperty(CommandProcessor.COMMAND_SCOPE)).andReturn("xxx");
-                EasyMock.expect(cd2Ref.getProperty(CommandProcessor.COMMAND_FUNCTION)).andReturn(
-                        new String[] {"aaa", "bbb"});
-                EasyMock.replay(cd2Ref);
-
-                ServiceEvent event2 = new ServiceEvent(ServiceEvent.REGISTERED, cd2Ref);
-                commandListener.serviceChanged(event2);
-                assertEquals(6, scp.getCommands().size());
-                assertTrue(scp.getCommands().contains("xxx:aaa"));
-                assertTrue(scp.getCommands().contains("xxx:bbb"));
-
-                return null;
-            }
-        });
-    }
-
-    void expectServiceTracker(final BundleContext bc, final String expectedFilter, final Map<String, ServiceListener> listeners) throws InvalidSyntaxException {
-        bc.addServiceListener(EasyMock.isA(ServiceListener.class), EasyMock.eq(expectedFilter));
-        EasyMock.expectLastCall().andAnswer(new IAnswer<Object>() {
-            @Override
-            public Object answer() throws Throwable {
-                listeners.put(expectedFilter, (ServiceListener) EasyMock.getCurrentArguments()[0]);
-                return null;
-            }
-        }).once();
-    }
-
-    // Subclass to provide access to some protected members
-    static class MySecuredCommandProcessorImpl extends SecuredCommandProcessorImpl {
-        public MySecuredCommandProcessorImpl(BundleContext bc) {
-            super(bc);
-        }
-
-        Map<String, Object> getConstants() {
-            return constants;
-        }
-    };
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/pom.xml
----------------------------------------------------------------------
diff --git a/shell/core/pom.xml b/shell/core/pom.xml
index 9ac3f14..f113baa 100644
--- a/shell/core/pom.xml
+++ b/shell/core/pom.xml
@@ -69,6 +69,11 @@
         </dependency>
         <dependency>
             <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.gogo.jline</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
             <artifactId>org.apache.felix.utils</artifactId>
             <scope>provided</scope>
         </dependency>
@@ -131,6 +136,8 @@
                         <Import-Package>
                             org.osgi.service.event;resolution:=optional,
                             org.apache.karaf.branding;resolution:=optional,
+                            !org.apache.felix.gogo.jline*,
+                            !org.apache.sshd.*,
                             *
                         </Import-Package>
                         <Export-Package>
@@ -147,6 +154,7 @@
                             org.apache.felix.utils.extender,
                             org.apache.felix.utils.manifest,
                             org.apache.felix.gogo.api,
+                            org.apache.felix.gogo.jline,
                             org.apache.felix.gogo.runtime,
                             org.apache.felix.gogo.runtime.threadio,
                             org.apache.felix.service.command,

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/api/console/Candidate.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/api/console/Candidate.java b/shell/core/src/main/java/org/apache/karaf/shell/api/console/Candidate.java
new file mode 100644
index 0000000..c882566
--- /dev/null
+++ b/shell/core/src/main/java/org/apache/karaf/shell/api/console/Candidate.java
@@ -0,0 +1,78 @@
+/*
+ * 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.api.console;
+
+import java.util.Objects;
+
+public class Candidate implements Comparable<Candidate> {
+
+    private final String value;
+    private final String displ;
+    private final String group;
+    private final String descr;
+    private final String suffix;
+    private final String key;
+    private final boolean complete;
+
+    public Candidate(String value) {
+        this(value, value, null, null, null, null, true);
+    }
+
+    public Candidate(String value, String displ, String group, String descr, String suffix, String key, boolean complete) {
+        Objects.requireNonNull(value);
+        this.value = value;
+        this.displ = displ;
+        this.group = group;
+        this.descr = descr;
+        this.suffix = suffix;
+        this.key = key;
+        this.complete = complete;
+    }
+
+    public String value() {
+        return value;
+    }
+
+    public String displ() {
+        return displ;
+    }
+
+    public String group() {
+        return group;
+    }
+
+    public String descr() {
+        return descr;
+    }
+
+    public String suffix() {
+        return suffix;
+    }
+
+    public String key() {
+        return key;
+    }
+
+    public boolean complete() {
+        return complete;
+    }
+
+    @Override
+    public int compareTo(Candidate o) {
+        return value.compareTo(o.value);
+    }
+}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/api/console/Completer.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/api/console/Completer.java b/shell/core/src/main/java/org/apache/karaf/shell/api/console/Completer.java
index 4f9f3d1..527f0db 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/api/console/Completer.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/api/console/Completer.java
@@ -18,6 +18,7 @@
  */
 package org.apache.karaf.shell.api.console;
 
+import java.util.ArrayList;
 import java.util.List;
 
 /**
@@ -35,4 +36,11 @@ public interface Completer {
      */
     int complete(Session session, CommandLine commandLine, List<String> candidates);
 
+    default void completeCandidates(Session session, CommandLine commandLine, List<Candidate> candidates) {
+        List<String> strings = new ArrayList<>();
+        complete(session, commandLine, strings);
+        for (String string : strings) {
+            candidates.add(new Candidate(string));
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/api/console/Session.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/api/console/Session.java b/shell/core/src/main/java/org/apache/karaf/shell/api/console/Session.java
index 4150ead..b9b549f 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/api/console/Session.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/api/console/Session.java
@@ -18,6 +18,7 @@
  */
 package org.apache.karaf.shell.api.console;
 
+import java.io.Closeable;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.PrintStream;
@@ -35,7 +36,7 @@ import java.io.PrintStream;
  *     <li>{@link Terminal}</li>
  * </ul>
  */
-public interface Session extends Runnable {
+public interface Session extends Runnable, Closeable {
 
     //
     // Session properties

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ActionCommand.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ActionCommand.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ActionCommand.java
index ac4be9f..0b815f6 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ActionCommand.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ActionCommand.java
@@ -23,6 +23,7 @@ import java.util.List;
 import org.apache.karaf.shell.api.action.Action;
 import org.apache.karaf.shell.api.action.Command;
 import org.apache.karaf.shell.api.action.Parsing;
+import org.apache.karaf.shell.api.console.Candidate;
 import org.apache.karaf.shell.api.console.CommandLine;
 import org.apache.karaf.shell.api.console.Completer;
 import org.apache.karaf.shell.api.console.Parser;
@@ -115,6 +116,14 @@ public class ActionCommand implements org.apache.karaf.shell.api.console.Command
             }
             return -1;
         }
+
+        @Override
+        public void completeCandidates(Session session, CommandLine commandLine, List<Candidate> candidates) {
+            Object service = session.getRegistry().getService(clazz);
+            if (service instanceof Completer) {
+                ((Completer) service).completeCandidates(session, commandLine, candidates);
+            }
+        }
     }
 
     public static class DelayedParser implements Parser {

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ArgumentCompleter.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ArgumentCompleter.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ArgumentCompleter.java
index c766c24..201212a 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ArgumentCompleter.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/action/command/ArgumentCompleter.java
@@ -34,6 +34,7 @@ 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.console.Candidate;
 import org.apache.karaf.shell.api.console.CommandLine;
 import org.apache.karaf.shell.api.console.Completer;
 import org.apache.karaf.shell.api.console.Session;
@@ -51,8 +52,8 @@ public class ArgumentCompleter implements Completer {
     private static final Logger LOGGER = LoggerFactory.getLogger(ArgumentCompleter.class);
 
     final ActionCommand command;
-    final Completer commandCompleter;
-    final Completer optionsCompleter;
+    final CandidateCompleter commandCompleter;
+    final CandidateCompleter optionsCompleter;
     final List<Completer> argsCompleters;
     final Map<String, Completer> optionalCompleters;
     final Map<Option, Field> fields = new HashMap<>();
@@ -66,7 +67,10 @@ public class ArgumentCompleter implements Completer {
         // Command name completer
         Command cmd = actionClass.getAnnotation(Command.class);
         String[] names = scoped || Session.SCOPE_GLOBAL.equals(cmd.scope()) ? new String[] { cmd.name() } : new String[] { cmd.name(), cmd.scope() + ":" + cmd.name() };
-        commandCompleter = new StringsCompleter(names);
+        commandCompleter = new CandidateCompleter();
+        for (String name : names) {
+            commandCompleter.addCandidate(name, cmd.description(), actionClass.getName());
+        }
         // Build options completer
         for (Class<?> type = actionClass; type != null; type = type.getSuperclass()) {
             for (Field field : type.getDeclaredFields()) {
@@ -94,8 +98,15 @@ public class ArgumentCompleter implements Completer {
         }
         options.put(HelpOption.HELP.name(), HelpOption.HELP);
 
+        optionsCompleter = new CandidateCompleter();
+        for (Map.Entry<String, Option> entry : options.entrySet()) {
+            optionsCompleter.addCandidate(
+                    entry.getKey(),
+                    entry.getValue().description(),
+                    actionClass.getName() + "/" + entry.getValue().name());
+        }
+
         argsCompleters = new ArrayList<>();
-        optionsCompleter = new StringsCompleter(options.keySet());
 
         boolean multi = false;
         for (int key = 0; key < arguments.size(); key++) {
@@ -187,7 +198,17 @@ public class ArgumentCompleter implements Completer {
         return completer;
     }
 
-    public int complete(Session session, final CommandLine list, final List<String> candidates) {
+    public int complete(Session session, final CommandLine commandLine, final List<String> candidates) {
+        List<Candidate> cands = new ArrayList<>();
+        completeCandidates(session, commandLine, cands);
+        for (Candidate cand : cands) {
+            candidates.add(cand.value());
+        }
+        return 0;
+    }
+
+    @Override
+    public void completeCandidates(Session session, final CommandLine list, List<Candidate> candidates) {
         int argIndex = list.getCursorArgumentIndex();
 
         Completer comp = null;
@@ -197,11 +218,11 @@ public class ArgumentCompleter implements Completer {
         if (index < argIndex) {
             // Verify scope
             if (!Session.SCOPE_GLOBAL.equals(command.getScope()) && !session.resolveCommand(args[index]).equals(command.getScope() + ":" + command.getName())) {
-                return -1;
+                return;
             }
             // Verify command name
             if (!verifyCompleter(session, commandCompleter, args[index])) {
-                return -1;
+                return;
             }
             index++;
         } else {
@@ -211,11 +232,11 @@ public class ArgumentCompleter implements Completer {
         if (comp == null) {
             while (index < argIndex && args[index].startsWith("-")) {
                 if (!verifyCompleter(session, optionsCompleter, args[index])) {
-                    return -1;
+                    return;
                 }
                 Option option = options.get(args[index]);
                 if (option == null) {
-                    return -1;
+                    return;
                 }
                 Field field = fields.get(option);
                 if (field != null && field.getType() != boolean.class && field.getType() != Boolean.class) {
@@ -229,7 +250,7 @@ public class ArgumentCompleter implements Completer {
                 comp = optionsCompleter;
             }
         }
-        //Now check for if last Option has a completer
+        // Now check for if last Option has a completer
         int lastAgurmentIndex = argIndex - 1;
         if (lastAgurmentIndex >= 1) {
             Option lastOption = options.get(args[lastAgurmentIndex]);
@@ -265,7 +286,7 @@ public class ArgumentCompleter implements Completer {
             while (index < argIndex) {
                 Completer sub = argsCompleters.get(indexArg >= argsCompleters.size() ? argsCompleters.size() - 1 : indexArg);
                 if (!verifyCompleter(session, sub, args[index])) {
-                    return -1;
+                    return;
                 }
                 index++;
                 indexArg++;
@@ -273,11 +294,13 @@ public class ArgumentCompleter implements Completer {
             comp = argsCompleters.get(indexArg >= argsCompleters.size() ? argsCompleters.size() - 1 : indexArg);
         }
 
-        int pos = comp.complete(session, list, candidates);
+        comp.completeCandidates(session, list, candidates);
 
+        /* TODO:JLINE
         if (pos == -1) {
             return -1;
         }
+        */
 
         /**
          *  Special case: when completing in the middle of a line, and the
@@ -290,6 +313,7 @@ public class ArgumentCompleter implements Completer {
          *  and hit TAB, we want "foo bar" instead of "foo  bar".
          */
 
+        /* TODO:JLINE
         String buffer = list.getBuffer();
         int cursor = list.getBufferPosition();
         if ((buffer != null) && (cursor != buffer.length()) && isDelimiter(buffer, cursor)) {
@@ -306,11 +330,13 @@ public class ArgumentCompleter implements Completer {
         }
 
         return pos;
+        */
     }
 
     protected boolean verifyCompleter(Session session, Completer completer, String argument) {
-        List<String> candidates = new ArrayList<>();
-        return completer.complete(session, new ArgumentCommandLine(argument, argument.length()), candidates) != -1 && !candidates.isEmpty();
+        List<Candidate> candidates = new ArrayList<>();
+        completer.completeCandidates(session, new ArgumentCommandLine(argument, argument.length()), candidates);
+        return !candidates.isEmpty();
     }
 
     /**
@@ -343,4 +369,35 @@ public class ArgumentCompleter implements Completer {
         return Character.isWhitespace(buffer.charAt(pos));
     }
 
+    static class CandidateCompleter implements Completer {
+
+        private final List<Candidate> candidates = new ArrayList<>();
+
+        public void addCandidate(String value, String desc) {
+            addCandidate(value, desc, null);
+        }
+
+        public void addCandidate(String value, String desc, String key) {
+            if (desc.endsWith(".")) {
+                desc = desc.substring(0, desc.length() - 1);
+            }
+            candidates.add(new Candidate(value, value, null, desc, null, key, true));
+        }
+
+        @Override
+        public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+            List<Candidate> cands = new ArrayList<>();
+            completeCandidates(session, commandLine, cands);
+            for (Candidate cand : cands) {
+                candidates.add(cand.value());
+            }
+            return 0;
+        }
+
+        @Override
+        public void completeCandidates(Session session, CommandLine commandLine, List<Candidate> candidates) {
+            candidates.addAll(this.candidates);
+        }
+    }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java
index 66d8f6a4..8a878d3 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CommandsCompleter.java
@@ -30,36 +30,53 @@ import java.util.Map;
 import java.util.Set;
 import java.util.TreeMap;
 
+import org.apache.karaf.shell.api.console.Candidate;
 import org.apache.karaf.shell.api.console.Command;
 import org.apache.karaf.shell.api.console.CommandLine;
 import org.apache.karaf.shell.api.console.Completer;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.api.console.SessionFactory;
-import org.apache.karaf.shell.support.completers.AggregateCompleter;
 import org.apache.karaf.shell.support.completers.ArgumentCommandLine;
 import org.apache.karaf.shell.support.completers.StringsCompleter;
+import org.jline.reader.LineReader;
+import org.jline.reader.ParsedLine;
 
 /**
  * Overall command line completer.
  */
-public class CommandsCompleter extends org.apache.karaf.shell.support.completers.CommandsCompleter {
+public class CommandsCompleter implements org.jline.reader.Completer {
 
     private final SessionFactory factory;
-    private final Map<String, Completer> globalCompleters = new HashMap<String, Completer>();
-    private final Map<String, Completer> localCompleters = new HashMap<String, Completer>();
+    private final Session session;
+    private final Map<String, Completer> globalCompleters = new HashMap<>();
+    private final Map<String, Completer> localCompleters = new HashMap<>();
     private final Completer aliasesCompleter = new SimpleCommandCompleter() {
         @Override
         protected Collection<String> getNames(Session session) {
             return getAliases(session);
         }
     };
-    private final List<Command> commands = new ArrayList<Command>();
+    private final List<Command> commands = new ArrayList<>();
 
-    public CommandsCompleter(SessionFactory factory) {
+    public CommandsCompleter(SessionFactory factory, Session session) {
         this.factory = factory;
+        this.session = session;
     }
 
-    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+    @Override
+    public void complete(LineReader reader, ParsedLine line, List<org.jline.reader.Candidate> candidates) {
+        CommandLine commandLine = new CommandLineImpl(line);
+        List<Candidate> cands = new ArrayList<>();
+        completeCandidates(session, commandLine, cands);
+        for (Candidate cand : cands) {
+            candidates.add(new org.jline.reader.Candidate(
+                    cand.value(), cand.displ(), cand.group(),
+                    cand.descr(), cand.suffix(), cand.key(),
+                    cand.complete()));
+        }
+    }
+
+    public void completeCandidates(Session session, CommandLine commandLine, List<Candidate> candidates) {
         Map<String, Completer>[] allCompleters = checkData();
 
         List<String> scopes = getCurrentScopes(session);
@@ -73,7 +90,7 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
             if (subShell.isEmpty()) {
                 subShell = Session.SCOPE_GLOBAL;
             }
-            List<Completer> completers = new ArrayList<Completer>();
+            List<Completer> completers = new ArrayList<>();
             for (String name : allCompleters[1].keySet()) {
                 if (name.startsWith(subShell + ":")) {
                     completers.add(allCompleters[1].get(name));
@@ -82,46 +99,50 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
             if (!subShell.equals(Session.SCOPE_GLOBAL)) {
                 completers.add(new StringsCompleter(new String[] { "exit" }));
             }
-            int res = new AggregateCompleter(completers).complete(session, commandLine, candidates);
-            Collections.sort(candidates);
-            return res;
+            completers.forEach(c -> c.completeCandidates(session, commandLine, candidates));
+            return;
         }
 
         // FIRST mode
         if (Session.COMPLETION_MODE_FIRST.equalsIgnoreCase(completion)) {
             if (!subShell.isEmpty()) {
-                List<Completer> completers = new ArrayList<Completer>();
+                List<Completer> completers = new ArrayList<>();
                 for (String name : allCompleters[1].keySet()) {
                     if (name.startsWith(subShell + ":")) {
                         completers.add(allCompleters[1].get(name));
                     }
                 }
-                int res = new AggregateCompleter(completers).complete(session, commandLine, candidates);
+                completers.forEach(c -> c.completeCandidates(session, commandLine, candidates));
                 if (!candidates.isEmpty()) {
-                    Collections.sort(candidates);
-                    return res;
+                    return;
                 }
             }
-            List<Completer> compl = new ArrayList<Completer>();
+            List<Completer> compl = new ArrayList<>();
             compl.add(aliasesCompleter);
             compl.addAll(allCompleters[0].values());
-            int res = new AggregateCompleter(compl).complete(session, commandLine, candidates);
-            Collections.sort(candidates);
-            return res;
+            compl.forEach(c -> c.completeCandidates(session, commandLine, candidates));
+            return;
         }
 
-        List<Completer> compl = new ArrayList<Completer>();
+        List<Completer> compl = new ArrayList<>();
         compl.add(aliasesCompleter);
         compl.addAll(allCompleters[0].values());
-        int res = new AggregateCompleter(compl).complete(session, commandLine, candidates);
-        Collections.sort(candidates);
-        return res;
+        compl.forEach(c -> c.completeCandidates(session, commandLine, candidates));
+    }
+
+    public int complete(Session session, CommandLine commandLine, List<String> candidates) {
+        List<Candidate> cands = new ArrayList<>();
+        completeCandidates(session, commandLine, cands);
+        for (Candidate cand : cands) {
+            candidates.add(cand.value());
+        }
+        return 0;
     }
 
     protected void sort(Map<String, Completer>[] completers, List<String> scopes) {
         ScopeComparator comparator = new ScopeComparator(scopes);
         for (int i = 0; i < completers.length; i++) {
-            Map<String, Completer> map = new TreeMap<String, Completer>(comparator);
+            Map<String, Completer> map = new TreeMap<>(comparator);
             map.putAll(completers[i]);
             completers[i] = map;
         }
@@ -186,11 +207,6 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
         return completion;
     }
 
-    protected String stripScope(String name) {
-        int index = name.indexOf(":");
-        return index > 0 ? name.substring(index + 1) : name;
-    }
-
     @SuppressWarnings("unchecked")
     protected Map<String, Completer>[] checkData() {
         // Copy the set to avoid concurrent modification exceptions
@@ -203,8 +219,8 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
         }
         if (update) {
             // get command aliases
-            Map<String, Completer> global = new HashMap<String, Completer>();
-            Map<String, Completer> local = new HashMap<String, Completer>();
+            Map<String, Completer> global = new HashMap<>();
+            Map<String, Completer> local = new HashMap<>();
 
             // add argument completers for each command
             for (Command command : commands) {
@@ -213,13 +229,13 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
                 Completer cl = command.getCompleter(true);
                 if (cg == null) {
                     if (Session.SCOPE_GLOBAL.equals(command.getScope())) {
-                        cg = new FixedSimpleCommandCompleter(Arrays.asList(command.getName()));
+                        cg = new FixedSimpleCommandCompleter(Collections.singletonList(command.getName()));
                     } else {
                         cg = new FixedSimpleCommandCompleter(Arrays.asList(key, command.getName()));
                     }
                 }
                 if (cl == null) {
-                    cl = new FixedSimpleCommandCompleter(Arrays.asList(command.getName()));
+                    cl = new FixedSimpleCommandCompleter(Collections.singletonList(command.getName()));
                 }
                 global.put(key, cg);
                 local.put(key, cl);
@@ -236,8 +252,8 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
         }
         synchronized (this) {
             return new Map[] {
-                    new HashMap<String, Completer>(this.globalCompleters),
-                    new HashMap<String, Completer>(this.localCompleters)
+                    new HashMap<>(this.globalCompleters),
+                    new HashMap<>(this.localCompleters)
             };
         }
     }
@@ -250,7 +266,7 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
     @SuppressWarnings("unchecked")
     private Set<String> getAliases(Session session) {
         Set<String> vars = ((Set<String>) session.get(null));
-        Set<String> aliases = new HashSet<String>();
+        Set<String> aliases = new HashSet<>();
         for (String var : vars) {
             Object content = session.get(var);
             if (content != null && "org.apache.felix.gogo.runtime.Closure".equals(content.getClass().getName())) {
@@ -282,7 +298,7 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
         protected abstract Collection<String> getNames(Session session);
 
         private boolean verifyCompleter(Session session, Completer completer, String argument) {
-            List<String> candidates = new ArrayList<String>();
+            List<String> candidates = new ArrayList<>();
             return completer.complete(session, new ArgumentCommandLine(argument, argument.length()), candidates) != -1 && !candidates.isEmpty();
         }
 
@@ -302,5 +318,43 @@ public class CommandsCompleter extends org.apache.karaf.shell.support.completers
         }
     }
 
+    private static class CommandLineImpl implements CommandLine {
+        private final ParsedLine line;
+
+        public CommandLineImpl(ParsedLine line) {
+            this.line = line;
+        }
+
+        @Override
+        public int getCursorArgumentIndex() {
+            return line.wordIndex();
+        }
+
+        @Override
+        public String getCursorArgument() {
+            return line.word();
+        }
+
+        @Override
+        public int getArgumentPosition() {
+            return line.wordCursor();
+        }
+
+        @Override
+        public String[] getArguments() {
+            return line.words().toArray(new String[line.words().size()]);
+        }
+
+        @Override
+        public int getBufferPosition() {
+            return line.cursor();
+        }
+
+        @Override
+        public String getBuffer() {
+            return line.line();
+        }
+    }
+
 }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CompleterAsCompletor.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CompleterAsCompletor.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CompleterAsCompletor.java
deleted file mode 100644
index f1e87c8..0000000
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/CompleterAsCompletor.java
+++ /dev/null
@@ -1,51 +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.impl.console;
-
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.apache.karaf.shell.api.console.CommandLine;
-import org.apache.karaf.shell.api.console.Completer;
-import org.apache.karaf.shell.api.console.Session;
-import org.apache.karaf.shell.impl.console.parsing.CommandLineParser;
-
-public class CompleterAsCompletor implements jline.console.completer.Completer {
-
-    private final Session session;
-    private final Completer completer;
-
-    public CompleterAsCompletor(Session session, Completer completer) {
-        this.session = session;
-        this.completer = completer;
-    }
-
-    @SuppressWarnings("unchecked")
-	public int complete(String buffer, int cursor, @SuppressWarnings("rawtypes") List candidates) {
-        AtomicInteger begOfLine = new AtomicInteger();
-        CommandLine cmdLine = CommandLineParser.buildCommandLine(session, buffer, cursor, begOfLine);
-        int res = completer.complete(session, cmdLine, candidates);
-        if (res >= 0) {
-            return res + begOfLine.get();
-        } else {
-            return res;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/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 2925346..413f2af 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
@@ -18,36 +18,26 @@
  */
 package org.apache.karaf.shell.impl.console;
 
-import java.io.CharArrayWriter;
-import java.io.Closeable;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.InterruptedIOException;
 import java.io.PrintStream;
-import java.io.Reader;
 import java.lang.management.ManagementFactory;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.util.List;
 import java.util.Map;
 import java.util.Properties;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.concurrent.BlockingQueue;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-import jline.UnsupportedTerminal;
-import jline.console.ConsoleReader;
-import jline.console.history.MemoryHistory;
-import jline.console.history.PersistentHistory;
 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.threadio.ThreadIO;
 import org.apache.karaf.shell.api.console.Command;
-import org.apache.karaf.shell.api.console.Completer;
 import org.apache.karaf.shell.api.console.History;
 import org.apache.karaf.shell.api.console.Registry;
 import org.apache.karaf.shell.api.console.Session;
@@ -58,6 +48,12 @@ 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.reader.impl.LineReaderImpl;
+import org.jline.reader.impl.history.history.FileHistory;
+import org.jline.reader.impl.history.history.MemoryHistory;
+import org.jline.terminal.impl.DumbTerminal;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -71,11 +67,7 @@ public class ConsoleSessionImpl implements Session {
     private static final Logger LOGGER = LoggerFactory.getLogger(ConsoleSessionImpl.class);
 
     // Input stream
-    final BlockingQueue<Integer> queue = new ArrayBlockingQueue<Integer>(1024);
-    final ConsoleInputStream console = new ConsoleInputStream();
-    final Pipe pipe = new Pipe();
     volatile boolean running;
-    volatile boolean eof;
 
     final SessionFactory factory;
     final ThreadIO threadIO;
@@ -87,10 +79,10 @@ public class ConsoleSessionImpl implements Session {
     final CommandSession session;
     final Registry registry;
     final Terminal terminal;
+    final org.jline.terminal.Terminal jlineTerminal;
     final History history;
-    final ConsoleReader reader;
+    final LineReaderImpl reader;
 
-    private boolean interrupt;
     private Thread thread;
 
     public ConsoleSessionImpl(SessionFactory factory,
@@ -111,16 +103,28 @@ public class ConsoleSessionImpl implements Session {
         this.closeCallback = closeCallback;
 
         // Terminal
-        terminal = term == null ? new JLineTerminal(new UnsupportedTerminal(), "dumb") : term;
+        if (term instanceof org.jline.terminal.Terminal) {
+            terminal = term;
+            jlineTerminal = (org.jline.terminal.Terminal) term;
+        } else if (term != null) {
+            terminal = term;
+//            jlineTerminal = new KarafTerminal(term);
+            // TODO:JLINE
+            throw new UnsupportedOperationException();
+        } else {
+            try {
+                jlineTerminal = new DumbTerminal(in, out);
+                terminal = new JLineTerminal(jlineTerminal);
+            } catch (IOException e) {
+                throw new RuntimeException("Unable to create terminal", e);
+            }
+        }
 
         // Console reader
         try {
-            System.setProperty("jline.sigcont", "true");
-            reader = new ConsoleReader(null,
-                    in != null ? console : null,
-                    out,
-                    terminal instanceof JLineTerminal ? ((JLineTerminal) terminal).getTerminal() : new KarafTerminal(terminal),
-                    encoding);
+            reader = new LineReaderImpl(
+                    jlineTerminal,
+                    "karaf");
         } catch (IOException e) {
             throw new RuntimeException("Error opening console reader", e);
         }
@@ -129,7 +133,7 @@ public class ConsoleSessionImpl implements Session {
         final File file = getHistoryFile();
         try {
             file.getParentFile().mkdirs();
-            reader.setHistory(new KarafFileHistory(file));
+            reader.setHistory(new FileHistory(file));
         } catch (Exception e) {
             LOGGER.error("Can not read history from file " + file + ". Using in memory history", e);
         }
@@ -150,8 +154,8 @@ public class ConsoleSessionImpl implements Session {
         registry.register(history);
 
         // Completers
-        Completer completer = new CommandsCompleter(factory);
-        reader.addCompleter(new CompleterAsCompletor(this, completer));
+        CommandsCompleter completer = new CommandsCompleter(factory, this);
+        reader.setCompleter(completer);
         registry.register(completer);
         registry.register(new CommandNamesCompleter());
         registry.register(new FileCompleter());
@@ -159,7 +163,9 @@ public class ConsoleSessionImpl implements Session {
         registry.register(new FileOrUriCompleter());
 
         // Session
-        session = processor.createSession(in != null ? console : null, out, err);
+        session = processor.createSession(jlineTerminal.input(),
+                                          jlineTerminal.output(),
+                                          jlineTerminal.output());
         Properties sysProps = System.getProperties();
         for (Object key : sysProps.keySet()) {
             session.put(key.toString(), sysProps.get(key));
@@ -175,17 +181,14 @@ public class ConsoleSessionImpl implements Session {
         session.put("USER", ShellUtil.getCurrentUserName());
         session.put("TERM", terminal.getType());
         session.put("APPLICATION", System.getProperty("karaf.name", "root"));
-        session.put("#LINES", new Function() {
-            public Object execute(CommandSession session, List<Object> arguments) throws Exception {
-                return Integer.toString(terminal.getHeight());
-            }
-        });
-        session.put("#COLUMNS", new Function() {
-            public Object execute(CommandSession session, List<Object> arguments) throws Exception {
-                return Integer.toString(terminal.getWidth());
-            }
-        });
+        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);
+
+        reader.setHighlighter(new org.apache.felix.gogo.jline.Highlighter(session));
+        reader.setParser(new org.apache.felix.gogo.jline.Parser());
+
     }
 
     /**
@@ -221,27 +224,24 @@ public class ConsoleSessionImpl implements Session {
         if (!running) {
             return;
         }
-        out.println();
-        if (reader.getHistory() instanceof PersistentHistory) {
-            try {
-                ((PersistentHistory) reader.getHistory()).flush();
-            } catch (IOException e) {
-                // ignore
-            }
+//        out.println();
+        try {
+            reader.getHistory().flush();
+        } catch (IOException e) {
+            // ignore
         }
+
         running = false;
-        pipe.interrupt();
         if (thread != Thread.currentThread()) {
             thread.interrupt();
         }
-        reader.shutdown();
         if (closeCallback != null) {
             closeCallback.run();
         }
-        if (terminal instanceof Closeable) {
+        if (terminal instanceof AutoCloseable) {
             try {
-                ((Closeable) terminal).close();
-            } catch (IOException e) {
+                ((AutoCloseable) terminal).close();
+            } catch (Exception e) {
                 // Ignore
             }
         }
@@ -254,7 +254,6 @@ public class ConsoleSessionImpl implements Session {
             threadIO.setStreams(session.getKeyboard(), out, err);
             thread = Thread.currentThread();
             running = true;
-            pipe.start();
             Properties brandingProps = Branding.loadBrandingProperties(terminal);
             welcome(brandingProps);
             setSessionProperties(brandingProps);
@@ -262,20 +261,15 @@ public class ConsoleSessionImpl implements Session {
             executeScript(scriptFileName);
             while (running) {
                 try {
-                    String command = readAndParseCommand();
-                    if (command == null) {
-                        break;
-                    }
-                    //session.getConsole().println("Executing: " + line);
+                    String command = reader.readLine(getPrompt());
                     Object result = session.execute(command);
                     if (result != null) {
                         session.getConsole().println(session.format(result, Converter.INSPECT));
                     }
-                } catch (InterruptedIOException e) {
-                    //System.err.println("^C");
-                    // TODO: interrupt current thread
-                } catch (InterruptedException e) {
-                    //interrupt current thread
+                } catch (UserInterruptException e) {
+                    // Ignore, loop again
+                } catch (EndOfFileException e) {
+                    break;
                 } catch (Throwable t) {
                     ShellUtil.logException(this, t);
                 }
@@ -335,12 +329,7 @@ public class ConsoleSessionImpl implements Session {
 
     @Override
     public String readLine(String prompt, Character mask) throws IOException {
-        reader.setHistoryEnabled(false);
-        try {
-            return reader.readLine(prompt, mask);
-        } finally {
-            reader.setHistoryEnabled(true);
-        }
+        return reader.readLine(prompt, mask);
     }
 
     private String loadCompletionMode() {
@@ -361,70 +350,15 @@ public class ConsoleSessionImpl implements Session {
         return mode;
     }
 
-    private String readAndParseCommand() throws IOException {
-        String command = null;
-        boolean first = true;
-        while (true) {
-            checkInterrupt();
-            String line = reader.readLine(first ? getPrompt() : "> ");
-            if (line == null) {
-                return null;
-            }
-            if (command == null) {
-                command = line;
-            } else {
-                if (command.charAt(command.length() - 1) == '\\') {
-                    command = command.substring(0, command.length() - 1) + line;
-                } else {
-                    command += "\n" + line;
-                }
-            }
-            if (reader.getHistory().size() == 0) {
-                reader.getHistory().add(command);
-            } else {
-                // jline doesn't add blank lines to the history so we don't
-                // need to replace the command in jline's console history with
-                // an indented one
-                if (command.length() > 0 && !" ".equals(command)) {
-                    reader.getHistory().replace(command);
-                }
-            }
-            if (command.length() > 0 && command.charAt(command.length() - 1) == '\\') {
-                first = false;
-            } else {
-                try {
-                    return CommandLineParser.parse(this, command);
-                } catch (Exception e) {
-                    first = false;
-                }
-            }
-        }
-    }
-
     private void executeScript(String scriptFileName) {
         if (scriptFileName != null) {
-            Reader r = null;
             try {
-                File scriptFile = new File(scriptFileName);
-                r = new InputStreamReader(new FileInputStream(scriptFile));
-                CharArrayWriter w = new CharArrayWriter();
-                int n;
-                char[] buf = new char[8192];
-                while ((n = r.read(buf)) > 0) {
-                    w.write(buf, 0, n);
-                }
-                session.execute(new String(w.toCharArray()));
+                String script = String.join("\n",
+                        Files.readAllLines(Paths.get(scriptFileName)));
+                session.execute(script);
             } catch (Exception e) {
                 LOGGER.debug("Error in initialization script", e);
                 System.err.println("Error in initialization script: " + e.getMessage());
-            } finally {
-                if (r != null) {
-                    try {
-                        r.close();
-                    } catch (IOException e) {
-                        // Ignore
-                    }
-                }
             }
         }
     }
@@ -480,131 +414,10 @@ public class ConsoleSessionImpl implements Session {
         }
     }
 
-    private void checkInterrupt() throws IOException {
-        if (Thread.interrupted() || interrupt) {
-            interrupt = false;
-            throw new InterruptedIOException("Keyboard interruption");
-        }
-    }
-
-    private void interrupt() {
-        interrupt = true;
-        thread.interrupt();
-    }
-
     private String getPid() {
         String name = ManagementFactory.getRuntimeMXBean().getName();
         String[] parts = name.split("@");
         return parts[0];
     }
 
-    private class ConsoleInputStream extends InputStream {
-        private int read(boolean wait) throws IOException {
-            if (!running) {
-                return -1;
-            }
-            checkInterrupt();
-            if (eof && queue.isEmpty()) {
-                return -1;
-            }
-            Integer i;
-            if (wait) {
-                try {
-                    i = queue.take();
-                } catch (InterruptedException e) {
-                    throw new InterruptedIOException();
-                }
-                checkInterrupt();
-            } else {
-                i = queue.poll();
-            }
-            if (i == null) {
-                return -1;
-            }
-            return i;
-        }
-
-        @Override
-        public int read() throws IOException {
-            return read(true);
-        }
-
-        @Override
-        public int read(byte b[], int off, int len) throws IOException {
-            if (b == null) {
-                throw new NullPointerException();
-            } else if (off < 0 || len < 0 || len > b.length - off) {
-                throw new IndexOutOfBoundsException();
-            } else if (len == 0) {
-                return 0;
-            }
-
-            int nb = 1;
-            int i = read(true);
-            if (i < 0) {
-                return -1;
-            }
-            b[off++] = (byte) i;
-            while (nb < len) {
-                i = read(false);
-                if (i < 0) {
-                    return nb;
-                }
-                b[off++] = (byte) i;
-                nb++;
-            }
-            return nb;
-        }
-
-        @Override
-        public int available() throws IOException {
-            return queue.size();
-        }
-    }
-
-    private class Pipe extends Thread {
-        public Pipe() {
-            super("Karaf shell pipe thread");
-            setDaemon(true);
-        }
-
-        public void run() {
-            boolean useAvailable = !System.getProperty("os.name").toLowerCase().contains("windows");
-            try {
-                while (running) {
-                    try {
-                        while (useAvailable && in.available() == 0) {
-                            if (!running) {
-                                return;
-                            }
-                            Thread.sleep(50);
-                        }
-                        int c = in.read();
-                        if (c == -1) {
-                            return;
-                        } else if (c == 4 && !ShellUtil.getBoolean(ConsoleSessionImpl.this, Session.IGNORE_INTERRUPTS)) {
-                            err.print("^D");
-                            err.flush();
-                            ConsoleSessionImpl.this.interrupt();
-                            return;
-                        } else if (c == 3 && !ShellUtil.getBoolean(ConsoleSessionImpl.this, Session.IGNORE_INTERRUPTS)) {
-                            err.println("^C");
-                            reader.getCursorBuffer().clear();
-                            ConsoleSessionImpl.this.interrupt();
-                        }
-                        queue.put(c);
-                    } catch (Throwable t) {
-                        return;
-                    }
-                }
-            } finally {
-                eof = true;
-                try {
-                    queue.put(-1);
-                } catch (InterruptedException e) {
-                }
-            }
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HeadlessSessionImpl.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HeadlessSessionImpl.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HeadlessSessionImpl.java
index e59eb82..7f951d3 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HeadlessSessionImpl.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/HeadlessSessionImpl.java
@@ -78,6 +78,7 @@ public class HeadlessSessionImpl implements Session {
             session.put("USER", ShellUtil.getCurrentUserName());
             session.put("APPLICATION", System.getProperty("karaf.name", "root"));
         }
+        session.currentDir(null);
     }
 
     public CommandSession getSession() {

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/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 6f69991..ef21593 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
@@ -22,9 +22,9 @@ import org.apache.karaf.shell.api.console.History;
 
 public class HistoryWrapper implements History {
 
-    private final jline.console.history.History history;
+    private final org.jline.reader.History history;
 
-    public HistoryWrapper(jline.console.history.History history) {
+    public HistoryWrapper(org.jline.reader.History history) {
         this.history = history;
     }
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/JLineTerminal.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/JLineTerminal.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/JLineTerminal.java
index c662aed..c45ba34 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/JLineTerminal.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/JLineTerminal.java
@@ -18,37 +18,59 @@
  */
 package org.apache.karaf.shell.impl.console;
 
-import java.io.Closeable;
 import java.io.IOException;
-import java.lang.reflect.InvocationHandler;
-import java.lang.reflect.Method;
-import java.lang.reflect.Proxy;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.util.EnumSet;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.CopyOnWriteArraySet;
 
-import org.apache.karaf.shell.api.console.Signal;
+import org.apache.karaf.shell.api.console.SignalListener;
 import org.apache.karaf.shell.api.console.Terminal;
-import org.apache.karaf.shell.support.terminal.SignalSupport;
+import org.jline.terminal.Attributes;
+import org.jline.terminal.Size;
+import org.jline.utils.InfoCmp.Capability;
+import org.jline.utils.NonBlockingReader;
 
-/**
- * Created by gnodet on 27/02/14.
- */
-public class JLineTerminal extends SignalSupport implements Terminal, Closeable {
+public class JLineTerminal implements Terminal, org.jline.terminal.Terminal {
 
-    private final jline.Terminal terminal;
-    private final String type;
+    private final org.jline.terminal.Terminal terminal;
+    private final ConcurrentMap<Signal, Set<SignalListener>> listeners = new ConcurrentHashMap<>();
+    private final ConcurrentMap<Signal, SignalHandler> handlers = new ConcurrentHashMap<>();
 
-    public JLineTerminal(jline.Terminal terminal, String type) {
+    public JLineTerminal(org.jline.terminal.Terminal terminal) {
         this.terminal = terminal;
-        this.type = type;
-        registerSignalHandler();
+        for (Signal signal : Signal.values()) {
+            terminal.handle(signal, this::handle);
+        }
     }
 
-    public jline.Terminal getTerminal() {
-        return terminal;
+    @Override
+    public String getType() {
+        return terminal.getType();
     }
 
     @Override
-    public String getType() {
-        return type;
+    public boolean puts(Capability capability, Object... params) {
+        return terminal.puts(capability, params);
+    }
+
+    @Override
+    public boolean getBooleanCapability(Capability capability) {
+        return terminal.getBooleanCapability(capability);
+    }
+
+    @Override
+    public Integer getNumericCapability(Capability capability) {
+        return terminal.getNumericCapability(capability);
+    }
+
+    @Override
+    public String getStringCapability(Capability capability) {
+        return terminal.getStringCapability(capability);
     }
 
     @Override
@@ -62,59 +84,177 @@ public class JLineTerminal extends SignalSupport implements Terminal, Closeable
     }
 
     @Override
+    public void flush() {
+        terminal.flush();
+    }
+
+    @Override
     public boolean isAnsiSupported() {
-        return terminal.isAnsiSupported();
+        return true;
     }
 
     @Override
     public boolean isEchoEnabled() {
-        return terminal.isEchoEnabled();
+        return terminal.echo();
     }
 
     @Override
     public void setEchoEnabled(boolean enabled) {
-        terminal.setEchoEnabled(enabled);
+        terminal.echo(enabled);
     }
 
     @Override
     public void close() throws IOException {
-        unregisterSignalHandler();
-    }
-
-    private void registerSignalHandler() {
-        try {
-            Class<?> signalClass = Class.forName("sun.misc.Signal");
-            Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
-            // Implement signal handler
-            Object signalHandler = Proxy.newProxyInstance(getClass().getClassLoader(),
-                    new Class<?>[]{signalHandlerClass}, new InvocationHandler() {
-                        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
-                            JLineTerminal.this.signal(Signal.WINCH);
-                            return null;
-                        }
-                    }
-            );
-            // Register the signal handler, this code is equivalent to:
-            // Signal.handle(new Signal("CONT"), signalHandler);
-            signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signalClass.getConstructor(String.class).newInstance("WINCH"), signalHandler);
-        } catch (Exception e) {
-            // Ignore this exception, if the above failed, the signal API is incompatible with what we're expecting
+        terminal.close();
+    }
+
+    @Override
+    public String getName() {
+        return terminal.getName();
+    }
+
+    @Override
+    public NonBlockingReader reader() {
+        return terminal.reader();
+    }
+
+    @Override
+    public PrintWriter writer() {
+        return terminal.writer();
+    }
+
+    @Override
+    public InputStream input() {
+        return terminal.input();
+    }
+
+    @Override
+    public OutputStream output() {
+        return terminal.output();
+    }
+
+    @Override
+    public Attributes enterRawMode() {
+        return terminal.enterRawMode();
+    }
+
+    @Override
+    public boolean echo() {
+        return terminal.echo();
+    }
+
+    @Override
+    public boolean echo(boolean echo) {
+        return terminal.echo(echo);
+    }
+
+    @Override
+    public Attributes getAttributes() {
+        return terminal.getAttributes();
+    }
+
+    @Override
+    public void setAttributes(Attributes attr) {
+        terminal.setAttributes(attr);
+    }
+
+    @Override
+    public Size getSize() {
+        return terminal.getSize();
+    }
+
+    @Override
+    public void setSize(Size size) {
+        terminal.setSize(size);
+    }
+
+    @Override
+    public void raise(Signal signal) {
+        terminal.raise(signal);
+    }
+
+    @Override
+    public SignalHandler handle(Signal signal, SignalHandler handler) {
+        return handlers.put(signal, handler);
+    }
 
+    @Override
+    public void addSignalListener(SignalListener listener) {
+        addSignalListener(listener, EnumSet.allOf(org.apache.karaf.shell.api.console.Signal.class));
+    }
+
+    @Override
+    public void addSignalListener(SignalListener listener, org.apache.karaf.shell.api.console.Signal... signals) {
+        for (org.apache.karaf.shell.api.console.Signal sig : signals) {
+            addSignalListener(listener, sig);
+        }
+    }
+
+    @Override
+    public void addSignalListener(SignalListener listener, EnumSet<org.apache.karaf.shell.api.console.Signal> signals) {
+        for (org.apache.karaf.shell.api.console.Signal sig : signals) {
+            addSignalListener(listener, sig);
+        }
+    }
+
+    private void addSignalListener(SignalListener listener, org.apache.karaf.shell.api.console.Signal signal) {
+        Set<SignalListener> ls = listeners.compute(signal(signal), (s, l) -> l != null ? l : new CopyOnWriteArraySet<>());
+        ls.add(listener);
+    }
+
+    @Override
+    public void removeSignalListener(SignalListener listener) {
+        for (Signal signal : Signal.values()) {
+            Set<SignalListener> ls = listeners.get(signal);
+            if (ls != null) {
+                ls.remove(listener);
+            }
         }
     }
 
-    private void unregisterSignalHandler() {
-        try {
-            Class<?> signalClass = Class.forName("sun.misc.Signal");
-            Class<?> signalHandlerClass = Class.forName("sun.misc.SignalHandler");
+    private Signal signal(org.apache.karaf.shell.api.console.Signal sig) {
+        switch (sig) {
+            case INT:
+                return Signal.INT;
+            case QUIT:
+                return Signal.QUIT;
+            case TSTP:
+                return Signal.TSTP;
+            case CONT:
+                return Signal.CONT;
+            case WINCH:
+                return Signal.WINCH;
+        }
+        throw new UnsupportedOperationException();
+    }
 
-            Object signalHandler = signalHandlerClass.getField("SIG_DFL").get(null);
-            // Register the signal handler, this code is equivalent to:
-            // Signal.handle(new Signal("CONT"), signalHandler);
-            signalClass.getMethod("handle", signalClass, signalHandlerClass).invoke(null, signalClass.getConstructor(String.class).newInstance("WINCH"), signalHandler);
-        } catch (Exception e) {
-            // Ignore this exception, if the above failed, the signal API is incompatible with what we're expecting
+    private org.apache.karaf.shell.api.console.Signal signal(Signal sig) {
+        switch (sig) {
+            case INT:
+                return org.apache.karaf.shell.api.console.Signal.INT;
+            case QUIT:
+                return org.apache.karaf.shell.api.console.Signal.QUIT;
+            case TSTP:
+                return org.apache.karaf.shell.api.console.Signal.TSTP;
+            case CONT:
+                return org.apache.karaf.shell.api.console.Signal.CONT;
+            case WINCH:
+                return org.apache.karaf.shell.api.console.Signal.WINCH;
+        }
+        throw new UnsupportedOperationException();
+    }
 
+    protected void handle(Signal signal) {
+        SignalHandler handler = handlers.get(signal);
+        if (handler != null) {
+            handler.handle(signal);
+        }
+        Set<SignalListener> sl = listeners.get(signal);
+        if (sl != null) {
+            for (SignalListener l : sl) {
+                l.signal(signal(signal));
+            }
         }
     }
+
 }

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafFileHistory.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafFileHistory.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafFileHistory.java
deleted file mode 100644
index aa4d2e4..0000000
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafFileHistory.java
+++ /dev/null
@@ -1,64 +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.impl.console;
-
-import java.io.File;
-import java.io.IOException;
-
-import jline.console.history.FileHistory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Override the FileHistory impl to trap failures due to the
- * user does not having write access to the history file.
- */
-public final class KarafFileHistory extends FileHistory {
-
-	static final Logger LOGGER = LoggerFactory.getLogger(KarafFileHistory.class);
-	boolean failed = false;
-
-	public KarafFileHistory(File file) throws IOException {
-		super(file);
-	}
-
-	@Override
-	public void flush() throws IOException {
-	    if( !failed ) {
-	        try {
-	            super.flush();
-	        } catch (IOException e) {
-	            failed = true;
-	            LOGGER.debug("Could not write history file: "+ getFile(), e);
-	        }
-	    }
-	}
-
-	@Override
-	public void purge() throws IOException {
-	    if( !failed ) {
-	        try {
-	            super.purge();
-	        } catch (IOException e) {
-	            failed = true;
-	            LOGGER.debug("Could not delete history file: "+ getFile(), e);
-	        }
-	    }
-	}
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafTerminal.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafTerminal.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafTerminal.java
index 643408a..169db55 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafTerminal.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/KarafTerminal.java
@@ -18,25 +18,29 @@
  */
 package org.apache.karaf.shell.impl.console;
 
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
 
-import jline.Terminal2;
-import jline.TerminalSupport;
-import jline.internal.InfoCmp;
 import org.apache.karaf.shell.api.console.Terminal;
+import org.jline.terminal.Attributes;
+import org.jline.terminal.Size;
+import org.jline.terminal.impl.AbstractTerminal;
+import org.jline.utils.InfoCmp;
+import org.jline.utils.InfoCmp.Capability;
+import org.jline.utils.NonBlockingReader;
 
-public class KarafTerminal extends TerminalSupport implements Terminal2 {
+public class KarafTerminal extends AbstractTerminal implements org.jline.terminal.Terminal {
 
     private final Terminal terminal;
-    private Set<String> bools = new HashSet<>();
-    private Map<String, Integer> ints = new HashMap<>();
-    private Map<String, String> strings = new HashMap<>();
 
-    public KarafTerminal(Terminal terminal) {
-        super(true);
+    public KarafTerminal(Terminal terminal) throws IOException {
+        super("Karaf", terminal.getType());
         this.terminal = terminal;
 
         String type = terminal.getType();
@@ -47,7 +51,7 @@ public class KarafTerminal extends TerminalSupport implements Terminal2 {
         try {
             caps = InfoCmp.getInfoCmp(type);
         } catch (Exception e) {
-            caps = InfoCmp.getAnsiCaps();
+            caps = InfoCmp.ANSI_CAPS;
         }
         try {
             InfoCmp.parseInfoCmp(caps, bools, ints, strings);
@@ -57,41 +61,49 @@ public class KarafTerminal extends TerminalSupport implements Terminal2 {
     }
 
     @Override
-    public synchronized boolean isAnsiSupported() {
-        return terminal.isAnsiSupported();
+    public NonBlockingReader reader() {
+        return null;
     }
 
     @Override
-    public int getWidth() {
-        return terminal.getWidth();
+    public PrintWriter writer() {
+        return null;
     }
 
     @Override
-    public int getHeight() {
-        return terminal.getHeight();
+    public InputStream input() {
+        return null;
     }
 
     @Override
-    public synchronized boolean isEchoEnabled() {
-        return false;
+    public OutputStream output() {
+        return null;
     }
 
     @Override
-    public synchronized void setEchoEnabled(boolean enabled) {
+    public Attributes getAttributes() {
+        return null;
     }
 
     @Override
-    public boolean getBooleanCapability(String capability) {
-        return bools.contains(capability);
+    public void setAttributes(Attributes attr) {
+
     }
 
     @Override
-    public Integer getNumericCapability(String capability) {
-        return ints.get(capability);
+    public Size getSize() {
+        int h = terminal.getHeight();
+        int w = terminal.getWidth();
+        return new Size(w, h);
     }
 
     @Override
-    public String getStringCapability(String capability) {
-        return strings.get(capability);
+    public void setSize(Size size) {
+        throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public void close() throws IOException {
     }
 }
+

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/TerminalFactory.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/TerminalFactory.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/TerminalFactory.java
deleted file mode 100644
index bae3a25..0000000
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/TerminalFactory.java
+++ /dev/null
@@ -1,47 +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.impl.console;
-
-import jline.NoInterruptUnixTerminal;
-import jline.Terminal;
-
-public class TerminalFactory {
-
-    private Terminal term;
-
-    public synchronized Terminal getTerminal() throws Exception {
-        if (term == null) {
-            init();
-        }
-        return term;
-    }
-
-    public void init() throws Exception {
-        jline.TerminalFactory.registerFlavor(jline.TerminalFactory.Flavor.UNIX, NoInterruptUnixTerminal.class);
-        term = jline.TerminalFactory.create();
-    }
-
-    public synchronized void destroy() throws Exception {
-        if (term != null) {
-            term.restore();
-            term = null;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java
index bd5acd9..79f0fbe 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/commands/help/wikidoc/AnsiPrintingWikiVisitor.java
@@ -18,10 +18,8 @@ package org.apache.karaf.shell.impl.console.commands.help.wikidoc;
 
 import java.io.PrintStream;
 
+import org.apache.karaf.shell.support.ansi.SimpleAnsi;
 import org.apache.karaf.shell.support.table.ShellTable;
-import org.fusesource.jansi.Ansi;
-import org.fusesource.jansi.Ansi.Attribute;
-import org.fusesource.jansi.Ansi.Color;
 
 /**
  * Translates the Wiki tags to Ansi escape sequences to display them on the console
@@ -62,19 +60,25 @@ public class AnsiPrintingWikiVisitor implements WikiVisitor {
 
 	@Override
 	public void heading(int level, String header) {
-		sb.append(Ansi.ansi().a(Attribute.INTENSITY_BOLD).a(header)
-				.a(Attribute.INTENSITY_BOLD_OFF).toString());
+		sb.append(SimpleAnsi.INTENSITY_BOLD)
+				.append(header)
+				.append(SimpleAnsi.INTENSITY_NORMAL);
 	}
 	
 	@Override
 	public void link(String target, String title) {
-		sb.append(Ansi.ansi().fg(Color.YELLOW)
-				.a(target).fg(Color.DEFAULT));
+		sb.append(SimpleAnsi.COLOR_YELLOW)
+				.append(target)
+				.append(SimpleAnsi.COLOR_DEFAULT);
 	}
 
 	@Override
 	public void enumeration(String text) {
-		sb.append(Ansi.ansi().a(" * ").fg(Color.CYAN).a(text).fg(Color.DEFAULT).a(" "));
+		sb.append(" * ")
+				.append(SimpleAnsi.COLOR_CYAN)
+				.append(text)
+				.append(SimpleAnsi.COLOR_DEFAULT)
+				.append(" ");
 	}
 
 	@Override
@@ -85,9 +89,9 @@ public class AnsiPrintingWikiVisitor implements WikiVisitor {
 	@Override
 	public void bold(boolean on) {
 		if (on) {
-			sb.append(Ansi.ansi().bold().toString());
+			sb.append(SimpleAnsi.INTENSITY_BOLD);
 		} else {
-			sb.append(Ansi.ansi().boldOff().toString());
+			sb.append(SimpleAnsi.INTENSITY_NORMAL);
 		}
 	}
 

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/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 3bd1b8f..57c0f95 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
@@ -27,7 +27,6 @@ import org.apache.karaf.shell.api.console.SessionFactory;
 import org.apache.karaf.shell.impl.action.command.ManagerImpl;
 import org.apache.karaf.shell.impl.action.osgi.CommandExtender;
 import org.apache.karaf.shell.impl.console.SessionFactoryImpl;
-import org.apache.karaf.shell.impl.console.TerminalFactory;
 import org.apache.karaf.shell.impl.console.osgi.secured.SecuredSessionFactoryImpl;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
@@ -49,7 +48,6 @@ public class Activator implements BundleActivator {
 
     private Closeable eventAdminListener;
 
-    private TerminalFactory terminalFactory;
     private LocalConsoleManager localConsoleManager;
 
     ServiceTracker<CommandLoggingFilter, CommandLoggingFilter> filterTracker;
@@ -64,7 +62,7 @@ public class Activator implements BundleActivator {
         sessionFactory.getCommandProcessor().addConstant(".context", context.getBundle(0).getBundleContext());
 
         final CopyOnWriteArraySet<CommandLoggingFilter> listeners = new CopyOnWriteArraySet<>();
-        filterTracker = new ServiceTracker<CommandLoggingFilter, CommandLoggingFilter>(
+        filterTracker = new ServiceTracker<>(
                 context, CommandLoggingFilter.class, new ServiceTrackerCustomizer<CommandLoggingFilter, CommandLoggingFilter>() {
             @Override
             public CommandLoggingFilter addingService(ServiceReference<CommandLoggingFilter> reference) {
@@ -104,8 +102,7 @@ public class Activator implements BundleActivator {
         actionExtender.start(context);
 
         if (Boolean.parseBoolean(context.getProperty(START_CONSOLE))) {
-            terminalFactory = new TerminalFactory();
-            localConsoleManager = new LocalConsoleManager(context, terminalFactory, sessionFactory);
+            localConsoleManager = new LocalConsoleManager(context, sessionFactory);
             localConsoleManager.start();
         }
     }
@@ -116,7 +113,6 @@ public class Activator implements BundleActivator {
         sessionFactoryRegistration.unregister();
         if (localConsoleManager != null) {
             localConsoleManager.stop();
-            terminalFactory.destroy();
         }
         sessionFactory.stop();
         actionExtender.stop(context);

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java
index 804f9c2..494fb65 100644
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java
+++ b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/LocalConsoleManager.java
@@ -18,6 +18,7 @@
  */
 package org.apache.karaf.shell.impl.console.osgi;
 
+import java.io.PrintStream;
 import java.nio.charset.Charset;
 import java.security.PrivilegedAction;
 
@@ -28,9 +29,9 @@ import org.apache.karaf.jaas.boot.principal.UserPrincipal;
 import org.apache.karaf.shell.api.console.Session;
 import org.apache.karaf.shell.api.console.SessionFactory;
 import org.apache.karaf.shell.impl.console.JLineTerminal;
-import org.apache.karaf.shell.impl.console.TerminalFactory;
 import org.apache.karaf.shell.support.ShellUtil;
 import org.apache.karaf.util.jaas.JaasHelper;
+import org.jline.terminal.TerminalBuilder;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
 
@@ -38,21 +39,18 @@ public class LocalConsoleManager {
 
     private SessionFactory sessionFactory;
     private BundleContext bundleContext;
-    private TerminalFactory terminalFactory;
     private Session session;
     private ServiceRegistration<?> registration;
     private boolean closing;
 
     public LocalConsoleManager(BundleContext bundleContext,
-                               TerminalFactory terminalFactory,
                                SessionFactory sessionFactory) throws Exception {
         this.bundleContext = bundleContext;
-        this.terminalFactory = terminalFactory;
         this.sessionFactory = sessionFactory;
     }
 
     public void start() throws Exception {
-        final jline.Terminal terminal = terminalFactory.getTerminal();
+        final org.jline.terminal.Terminal terminal = TerminalBuilder.terminal();
         final Runnable callback = new Runnable() {
             public void run() {
                 try {
@@ -71,10 +69,10 @@ public class LocalConsoleManager {
             public Session run() {
                 String encoding = getEncoding();
                 session = sessionFactory.create(
-                                      StreamWrapUtil.reWrapIn(terminal, System.in),
-                                      StreamWrapUtil.reWrap(System.out), 
-                                      StreamWrapUtil.reWrap(System.err),
-                                      new JLineTerminal(terminal, System.getenv("TERM")),
+                                      terminal.input(),
+                                      new PrintStream(terminal.output()),
+                                      new PrintStream(terminal.output()),
+                                      new JLineTerminal(terminal),
                                       encoding, 
                                       callback);
                 registration = bundleContext.registerService(Session.class, session, null);

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/StreamWrapUtil.java
----------------------------------------------------------------------
diff --git a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/StreamWrapUtil.java b/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/StreamWrapUtil.java
deleted file mode 100644
index 2b3afcd..0000000
--- a/shell/core/src/main/java/org/apache/karaf/shell/impl/console/osgi/StreamWrapUtil.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.impl.console.osgi;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.Method;
-
-import jline.Terminal;
-import org.fusesource.jansi.AnsiConsole;
-
-final class StreamWrapUtil {
-    private StreamWrapUtil() {
-    }
-
-    private static Object invokePrivateMethod(Object o, String methodName, Object[] params) throws Exception {
-        final Method methods[] = o.getClass().getDeclaredMethods();
-        for (int i = 0; i < methods.length; ++i) {
-            if (methodName.equals(methods[i].getName())) {
-                methods[i].setAccessible(true);
-                return methods[i].invoke(o, params);
-            }
-        }
-        return o;
-    }
-
-    /**
-     * unwrap stream so it can be recognized by the terminal and wrapped to get
-     * special keys in windows
-     * 
-     * @param stream
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    private static <T> T unwrapBIS(T stream) {
-        try {
-            return (T) invokePrivateMethod(stream, "getInIfOpen", null);
-        } catch (Throwable t) {
-            return stream;
-        }
-    }
-
-    private static PrintStream wrap(PrintStream stream) {
-        OutputStream o = AnsiConsole.wrapOutputStream(stream);
-        if (o instanceof PrintStream) {
-            return ((PrintStream) o);
-        } else {
-            return new PrintStream(o);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private static <T> T unwrap(T stream) {
-        try {
-            Method mth = stream.getClass().getMethod("getRoot");
-            return (T) mth.invoke(stream);
-        } catch (Throwable t) {
-            return stream;
-        }
-    }
-
-    static InputStream reWrapIn(Terminal terminal, InputStream stream) {
-        try {
-            return terminal.wrapInIfNeeded(unwrapBIS(unwrap(stream)));
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    static PrintStream reWrap(PrintStream stream) {
-        return wrap(unwrap(stream));
-    }
-}


[4/6] karaf git commit: [KARAF-4570] Upgrade to JLine 3

Posted by gn...@apache.org.
http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/DelayedStarted.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/DelayedStarted.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/DelayedStarted.java
deleted file mode 100644
index 87fb284..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/DelayedStarted.java
+++ /dev/null
@@ -1,87 +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.console.impl.jline;
-
-import java.io.InputStream;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.FrameworkEvent;
-import org.osgi.framework.FrameworkListener;
-import org.osgi.framework.startlevel.FrameworkStartLevel;
-
-/**
- * Delay the start of the console until the desired start level is reached or enter is pressed
- */
-class DelayedStarted extends Thread implements FrameworkListener {
-    private static final String SYSTEM_PROP_KARAF_CONSOLE_STARTED = "karaf.console.started";
-
-	private final AtomicBoolean started = new AtomicBoolean(false);
-    private final InputStream in;
-	private final Runnable console;
-	private final BundleContext bundleContext;
-
-    DelayedStarted(Runnable console, String name, BundleContext bundleContext, InputStream in) {
-        super(name);
-        this.console = console;
-        this.bundleContext = bundleContext;
-        this.in = in;
-        int defaultStartLevel = Integer.parseInt(System.getProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL));
-        int startLevel = bundleContext.getBundle(0).adapt(FrameworkStartLevel.class).getStartLevel();
-        if (startLevel >= defaultStartLevel) {
-            started.set(true);
-        } else {
-            bundleContext.addFrameworkListener(this);
-            frameworkEvent(new FrameworkEvent(FrameworkEvent.STARTLEVEL_CHANGED, bundleContext.getBundle(), null));
-        }
-    }
-
-    public void run() {
-        try {
-            while (!started.get()) {
-                if (in.available() == 0) {
-                    Thread.sleep(10);
-                }
-                while (in.available() > 0) {
-                    char ch = (char) in.read();
-                    if (ch == '\r' || ch == '\n') {
-                        started.set(true);
-                        break;
-                    }
-                }
-            }
-        } catch (Throwable t) {
-            // Ignore
-        }
-
-        // Signal to the main module that it can stop displaying the startup progress
-        System.setProperty(SYSTEM_PROP_KARAF_CONSOLE_STARTED, "true");
-        this.bundleContext.removeFrameworkListener(this);
-        console.run();
-    }
-
-    public void frameworkEvent(FrameworkEvent event) {
-        if (event.getType() == FrameworkEvent.STARTLEVEL_CHANGED) {
-            int defaultStartLevel = Integer.parseInt(System.getProperty(Constants.FRAMEWORK_BEGINNING_STARTLEVEL));
-            int startLevel = this.bundleContext.getBundle(0).adapt(FrameworkStartLevel.class).getStartLevel();
-            if (startLevel >= defaultStartLevel) {
-                started.set(true);
-            }
-        }
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/KarafFileHistory.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/KarafFileHistory.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/KarafFileHistory.java
deleted file mode 100644
index 8510a3a..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/KarafFileHistory.java
+++ /dev/null
@@ -1,65 +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.console.impl.jline;
-
-import java.io.File;
-import java.io.IOException;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import jline.console.history.FileHistory;
-
-/**
- * Override the FileHistory impl to trap failures due to the
- * user does not having write access to the history file.
- */
-public final class KarafFileHistory extends FileHistory {
-
-	static final Logger LOGGER = LoggerFactory.getLogger(KarafFileHistory.class);
-	boolean failed = false;
-
-	public KarafFileHistory(File file) throws IOException {
-		super(file);
-	}
-
-	@Override
-	public void flush() throws IOException {
-	    if( !failed ) {
-	        try {
-	            super.flush();
-	        } catch (IOException e) {
-	            failed = true;
-	            LOGGER.debug("Could not write history file: "+ getFile(), e);
-	        }
-	    }
-	}
-
-	@Override
-	public void purge() throws IOException {
-	    if( !failed ) {
-	        try {
-	            super.purge();
-	        } catch (IOException e) {
-	            failed = true;
-	            LOGGER.debug("Could not delete history file: "+ getFile(), e);
-	        }
-	    }
-	}
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java
deleted file mode 100644
index 7d52a5b..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/LocalConsoleManager.java
+++ /dev/null
@@ -1,163 +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.console.impl.jline;
-
-import java.nio.charset.Charset;
-import java.security.PrivilegedAction;
-
-import javax.security.auth.Subject;
-
-import jline.Terminal;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.karaf.jaas.boot.principal.RolePrincipal;
-import org.apache.karaf.jaas.boot.principal.UserPrincipal;
-import org.apache.karaf.shell.console.Console;
-import org.apache.karaf.shell.console.factory.ConsoleFactory;
-import org.apache.karaf.shell.util.ShellUtil;
-import org.apache.karaf.util.jaas.JaasHelper;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.ServiceRegistration;
-
-public class LocalConsoleManager {
-
-    private ConsoleFactory consoleFactory;
-    private BundleContext bundleContext;
-    private TerminalFactory terminalFactory;
-    private Console console;
-    private boolean start;
-    private final int defaultStartLevel;
-    private ServiceRegistration<?> registration;
-
-    public LocalConsoleManager(boolean start, 
-            String defaultStartLevel,
-            BundleContext bundleContext, 
-            TerminalFactory terminalFactory, 
-            ConsoleFactory consoleFactory) throws Exception {
-        this.start = start;
-        this.defaultStartLevel = Integer.parseInt(defaultStartLevel);
-        this.bundleContext = bundleContext;
-        this.terminalFactory = terminalFactory;
-        this.consoleFactory = consoleFactory;
-        start();
-    }
-
-    public void start() throws Exception {
-        if (!start) {
-            return;
-        }
-        
-
-        final Terminal terminal = terminalFactory.getTerminal();
-        final Runnable callback = new Runnable() {
-            public void run() {
-                try {
-                    bundleContext.getBundle(0).stop();
-                } catch (Exception e) {
-                    // Ignore
-                }
-            }
-        };
-
-        
-        final Subject subject = createLocalKarafSubject();    
-        this.console = JaasHelper.<Console>doAs(subject, new PrivilegedAction<Console>() {
-            public Console run() {
-                String encoding = getEncoding();
-                console = consoleFactory.create(
-                                      StreamWrapUtil.reWrapIn(terminal, System.in), 
-                                      StreamWrapUtil.reWrap(System.out), 
-                                      StreamWrapUtil.reWrap(System.err),
-                                      terminal, 
-                                      encoding, 
-                                      callback);
-                String name = "Karaf local console user " + ShellUtil.getCurrentUserName();
-                boolean delayconsole = Boolean.parseBoolean(System.getProperty("karaf.delay.console"));
-                if (delayconsole) {
-                    DelayedStarted watcher = new DelayedStarted(console, name, bundleContext, System.in);
-                    new Thread(watcher).start();
-                } else {
-                    new Thread(console, name).start();
-                }
-                return console;
-            }
-        });
-        registration = bundleContext.registerService(CommandSession.class, console.getSession(), null);
-
-    }
-
-    /**
-     * Get the default encoding.  Will first look at the LC_CTYPE environment variable, then the input.encoding
-     * system property, then the default charset according to the JVM.
-     *
-     * @return The default encoding to use when none is specified.
-     */
-    public static String getEncoding() {
-        // LC_CTYPE is usually in the form en_US.UTF-8
-        String envEncoding = extractEncodingFromCtype(System.getenv("LC_CTYPE"));
-        if (envEncoding != null) {
-            return envEncoding;
-        }
-        return System.getProperty("input.encoding", Charset.defaultCharset().name());
-    }
-
-    /**
-     * Parses the LC_CTYPE value to extract the encoding according to the POSIX standard, which says that the LC_CTYPE
-     * environment variable may be of the format <code>[language[_territory][.codeset][@modifier]]</code>
-     *
-     * @param ctype The ctype to parse, may be null
-     * @return The encoding, if one was present, otherwise null
-     */
-    static String extractEncodingFromCtype(String ctype) {
-        if (ctype != null && ctype.indexOf('.') > 0) {
-            String encodingAndModifier = ctype.substring(ctype.indexOf('.') + 1);
-            if (encodingAndModifier.indexOf('@') > 0) {
-                return encodingAndModifier.substring(0, encodingAndModifier.indexOf('@'));
-            } else {
-                return encodingAndModifier;
-            }
-        }
-        return null;
-    }
-
-    private Subject createLocalKarafSubject() {
-        final Subject subject = new Subject();
-        subject.getPrincipals().add(new UserPrincipal("karaf"));
-
-        String roles = System.getProperty("karaf.local.roles");
-        if (roles != null) {
-            for (String role : roles.split("[,]")) {
-                subject.getPrincipals().add(new RolePrincipal(role.trim()));
-            }
-        }
-        return subject;
-    }
-
-    public void stop() throws Exception {
-        if (registration != null) {
-            registration.unregister();
-        }
-        // The bundle is stopped
-        // so close the console and remove the callback so that the
-        // osgi framework isn't stopped
-        if (console != null) {
-            console.close(false);
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/StreamWrapUtil.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/StreamWrapUtil.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/StreamWrapUtil.java
deleted file mode 100644
index f6aa549..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/StreamWrapUtil.java
+++ /dev/null
@@ -1,92 +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.console.impl.jline;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
-import java.lang.reflect.Method;
-
-import jline.Terminal;
-
-import org.fusesource.jansi.AnsiConsole;
-
-final class StreamWrapUtil {
-    private StreamWrapUtil() {
-    }
-
-    private static Object invokePrivateMethod(Object o, String methodName, Object[] params) throws Exception {
-        final Method methods[] = o.getClass().getDeclaredMethods();
-        for (int i = 0; i < methods.length; ++i) {
-            if (methodName.equals(methods[i].getName())) {
-                methods[i].setAccessible(true);
-                return methods[i].invoke(o, params);
-            }
-        }
-        return o;
-    }
-
-    /**
-     * unwrap stream so it can be recognized by the terminal and wrapped to get
-     * special keys in windows
-     * 
-     * @param stream
-     * @return
-     */
-    @SuppressWarnings("unchecked")
-    private static <T> T unwrapBIS(T stream) {
-        try {
-            return (T) invokePrivateMethod(stream, "getInIfOpen", null);
-        } catch (Throwable t) {
-            return stream;
-        }
-    }
-
-    private static PrintStream wrap(PrintStream stream) {
-        OutputStream o = AnsiConsole.wrapOutputStream(stream);
-        if (o instanceof PrintStream) {
-            return ((PrintStream) o);
-        } else {
-            return new PrintStream(o);
-        }
-    }
-
-    @SuppressWarnings("unchecked")
-    private static <T> T unwrap(T stream) {
-        try {
-            Method mth = stream.getClass().getMethod("getRoot");
-            return (T) mth.invoke(stream);
-        } catch (Throwable t) {
-            return stream;
-        }
-    }
-
-    static InputStream reWrapIn(Terminal terminal, InputStream stream) {
-        try {
-            return terminal.wrapInIfNeeded(unwrapBIS(unwrap(stream)));
-        } catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-    static PrintStream reWrap(PrintStream stream) {
-        return wrap(unwrap(stream));
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/TerminalFactory.java
----------------------------------------------------------------------
diff --git a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/TerminalFactory.java b/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/TerminalFactory.java
deleted file mode 100644
index ac1601b..0000000
--- a/shell/console/src/main/java/org/apache/karaf/shell/console/impl/jline/TerminalFactory.java
+++ /dev/null
@@ -1,47 +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.console.impl.jline;
-
-import jline.NoInterruptUnixTerminal;
-import jline.Terminal;
-
-public class TerminalFactory {
-
-    private Terminal term;
-
-    public synchronized Terminal getTerminal() throws Exception {
-        if (term == null) {
-            init();
-        }
-        return term;
-    }
-
-    public void init() throws Exception {
-        jline.TerminalFactory.registerFlavor(jline.TerminalFactory.Flavor.UNIX, NoInterruptUnixTerminal.class);
-        term = jline.TerminalFactory.create();
-    }
-
-    public synchronized void destroy() throws Exception {
-        if (term != null) {
-            term.restore();
-            term = null;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/Context.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/Context.java b/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/Context.java
deleted file mode 100644
index e378789..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/Context.java
+++ /dev/null
@@ -1,67 +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.basic;
-
-import org.apache.felix.gogo.runtime.CommandProcessorImpl;
-import org.apache.felix.gogo.runtime.CommandSessionImpl;
-import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
-import org.apache.felix.service.command.CommandSession;
-
-public class Context extends CommandProcessorImpl
-{
-    public static final String EMPTY = "";
-    CommandSessionImpl session;
-    static ThreadIOImpl threadio;
-
-    static
-    {
-        threadio = new ThreadIOImpl();
-        threadio.start();
-    }
-
-    public Context()
-    {
-        super(threadio);
-        addCommand("shell", this, "addCommand");
-        addCommand("shell", this, "removeCommand");
-        addCommand("shell", this, "eval");
-        session = (CommandSessionImpl) createSession(System.in, System.out, System.err);
-    }
-
-
-    public Object execute(CharSequence source) throws Exception
-    {
-        return session.execute(source);
-    }
-
-    public void set(String name, Object value)
-    {
-        session.put(name, value);
-    }
-
-    public Object get(String name)
-    {
-        return session.get(name);
-    }
-
-    public CommandSession getSession() {
-        return session;
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/SimpleSubShell.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/SimpleSubShell.java b/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/SimpleSubShell.java
deleted file mode 100644
index 77e9b57..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/SimpleSubShell.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.basic;
-
-import org.apache.karaf.shell.commands.Action;
-import org.apache.karaf.shell.commands.basic.SimpleCommand;
-import org.apache.karaf.shell.console.SubShellAction;
-
-public class SimpleSubShell extends SimpleCommand {
-
-    private final String subshell;
-
-    public SimpleSubShell(String subshell) {
-        super(SubShellAction.class);
-        this.subshell = subshell;
-    }
-
-    @Override
-    public Action createNewAction() {
-        SubShellAction action = (SubShellAction) super.createNewAction();
-        action.setSubShell(subshell);
-        return action;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/TestCommands.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/TestCommands.java b/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/TestCommands.java
deleted file mode 100644
index ce55446..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/commands/basic/TestCommands.java
+++ /dev/null
@@ -1,184 +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.basic;
-
-import java.util.List;
-import java.util.Arrays;
-import java.io.IOException;
-import java.io.StringWriter;
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.shell.commands.Action;
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Command;
-import org.apache.karaf.shell.commands.CommandException;
-import org.apache.karaf.shell.commands.Option;
-import org.apache.karaf.shell.commands.basic.SimpleCommand;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.karaf.shell.console.ExitAction;
-
-public class TestCommands extends TestCase {
-
-    public void testSubShellScope() throws Exception {
-        Context c = new Context();
-        c.set("SCOPE", "*");
-        c.addCommand("*", new SimpleSubShell("foo"), "foo");
-        c.addCommand("*", new SimpleCommand(ExitAction.class), "exit");
-
-        String scope = (String) c.get("SCOPE");
-        c.execute("foo");
-        assertEquals("foo:" + scope, c.get("SCOPE"));
-        c.execute("exit");
-        assertEquals(scope, c.get("SCOPE"));
-    }
-
-    public void testPrompt() throws Exception {
-        Context c = new Context();
-        c.addCommand("echo", this);
-        c.set("USER", "test");
-        c.set("APPLICATION", "karaf");
-        //c.set("SCOPE", "");
-        Object p = c.execute("echo \"@|bold ${USER}|@${APPLICATION}:@|bold ${SCOPE}|> \"");
-        System.out.println("Prompt: " + p);
-    }
-
-    public void testCommand() throws Exception {
-        Context c = new Context();
-        c.addCommand("*", this, "capture");
-        c.addCommand("*", new SimpleCommand(MyAction.class), "my-action");
-
-        // Test help
-        Object help = c.execute("my-action --help | capture");
-        assertTrue(help instanceof String);
-        assertTrue(((String) help).indexOf("My Action") >= 0);
-        assertTrue(((String) help).indexOf("First option") >= 0);
-        assertTrue(((String) help).indexOf("Bundle ids") >= 0);
-
-        // Test required argument
-        try {
-            c.execute("my-action");
-            fail("Action should have thrown an exception because of a missing argument");
-        } catch (CommandException e) {
-            // ignore
-        }
-
-        // Test required argument
-        assertEquals(Arrays.asList(3), c.execute("my-action 3"));
-
-        // Test required argument
-        assertEquals(Arrays.asList(3), c.execute("my-action 3"));
-
-        // Test required argument
-        assertEquals(Arrays.asList(3, 5), c.execute("my-action 3 5"));
-
-        // Test option
-        assertEquals(Arrays.asList(4), c.execute("my-action -i 3"));
-
-        // Test option alias
-        assertEquals(Arrays.asList(4), c.execute("my-action --increment 3"));
-    }
-
-    public void testCommandTwoArguments() throws Exception {
-        Context c = new Context();
-        c.addCommand("*", new SimpleCommand(MyActionTwoArguments.class), "my-action-two-arguments");
-
-        // test required arguments
-        try {
-            c.execute("my-action-two-arguments");
-            fail("Action should have thrown an exception because of a missing argument");
-        } catch (CommandException e) {
-            assertEquals("Argument one is required", e.getMessage());
-        }
-
-        try {
-            c.execute("my-action-two-arguments 1");
-            fail("Action should have thrown an exception because of a missing argument");
-        } catch (CommandException e) {
-            assertEquals("Argument two is required", e.getMessage());
-        }
-
-        c.execute("my-action-two-arguments 1 2");
-    }
-
-    public String capture() throws IOException {
-        StringWriter sw = new StringWriter();
-        BufferedReader rdr = new BufferedReader(new InputStreamReader(System.in));
-        String s = rdr.readLine();
-        while (s != null) {
-            sw.write(s);
-            s = rdr.readLine();
-        }
-        return sw.toString();
-    }
-
-    public CharSequence echo(Object args[]) {
-        if (args == null) {
-            return "";
-        }
-
-        StringBuilder sb = new StringBuilder();
-        String del = "";
-        for (Object arg : args) {
-            sb.append(del);
-            if (arg != null) {
-                sb.append(arg);
-                del = " ";
-            }
-        }
-        return sb;
-    }
-
-    @Command(scope = "test", name = "my-action", description = "My Action")
-    public static class MyAction implements Action {
-
-        @Option(name = "-i", aliases = {"--increment"}, description = "First option")
-        private boolean increment;
-
-        @Argument(name = "ids", description = "Bundle ids", required = true, multiValued = true)
-        private List<Integer> ids;
-
-        public Object execute(CommandSession session) throws Exception {
-            if (increment) {
-                for (int i = 0; i < ids.size(); i++) {
-                    ids.set(i, ids.get(i) + 1);
-                }
-            }
-            return ids;
-        }
-    }
-
-    @Command(scope = "test", name = "my-action-two-arguments", description = "My Action with two arguments")
-    public static class MyActionTwoArguments implements Action {
-
-        @Argument(index = 0, name = "one", description = "one description", required = true, multiValued = false)
-        private String one;
-
-        @Argument(index = 1, name = "two", description = "two description", required = true, multiValued = false)
-        private String two;
-
-        public Object execute(CommandSession session) throws Exception {
-            return null;
-        }
-
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/commands/meta/TestFormatting.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/commands/meta/TestFormatting.java b/shell/console/src/test/java/org/apache/karaf/shell/commands/meta/TestFormatting.java
deleted file mode 100644
index 24762f5..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/commands/meta/TestFormatting.java
+++ /dev/null
@@ -1,35 +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.meta;
-
-import java.io.ByteArrayOutputStream;
-import java.io.PrintStream;
-
-import junit.framework.TestCase;
-
-import org.apache.karaf.shell.commands.meta.ActionMetaData;
-
-public class TestFormatting extends TestCase {
-    
-    public void testFormat() throws Exception {
-        ByteArrayOutputStream baos = new ByteArrayOutputStream();
-        ActionMetaData.printFormatted("  ", "  This is a test with a long paragraph\n\n  with an indented paragraph\nAnd another one\n", 20, new PrintStream(baos, true), true);
-        System.err.println(baos.toString());
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/completer/ArgumentCompleterTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/ArgumentCompleterTest.java b/shell/console/src/test/java/org/apache/karaf/shell/console/completer/ArgumentCompleterTest.java
deleted file mode 100644
index e140ab3..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/ArgumentCompleterTest.java
+++ /dev/null
@@ -1,145 +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.console.completer;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-import org.apache.karaf.shell.commands.Action;
-import org.apache.karaf.shell.commands.Option;
-import org.apache.karaf.shell.commands.basic.SimpleCommand;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.karaf.shell.console.CompletableFunction;
-import org.apache.karaf.shell.console.Completer;
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-public class ArgumentCompleterTest extends CompleterTestSupport {
-
-    @Test
-    public void testParser1() throws Exception {
-        Parser parser = new Parser("echo foo | cat bar ; ta", 23);
-        List<List<List<String>>> p = parser.program();
-        assertEquals(1, parser.c0);
-        assertEquals(0, parser.c1);
-        assertEquals(0, parser.c2);
-        assertEquals(2, parser.c3);
-    }
-
-    @Test
-    public void testParser2() throws Exception {
-        Parser parser = new Parser("echo foo ; cat bar | ta", 23);
-        List<List<List<String>>> p = parser.program();
-        assertEquals(1, parser.c0);
-        assertEquals(1, parser.c1);
-        assertEquals(0, parser.c2);
-        assertEquals(2, parser.c3);
-    }
-
-    @Test
-    public void testParser3() throws Exception {
-        Parser parser = new Parser("echo foo ; cat bar | ta", 22);
-        List<List<List<String>>> p = parser.program();
-        assertEquals(1, parser.c0);
-        assertEquals(1, parser.c1);
-        assertEquals(0, parser.c2);
-        assertEquals(1, parser.c3);
-    }
-
-    @Test
-    public void testParser4() throws Exception {
-        Parser parser = new Parser("echo foo ; cat bar | ta reta", 27);
-        List<List<List<String>>> p = parser.program();
-        assertEquals(1, parser.c0);
-        assertEquals(1, parser.c1);
-        assertEquals(1, parser.c2);
-        assertEquals(3, parser.c3);
-    }
-
-    @Test
-    public void testParser5() throws Exception {
-        Parser parser = new Parser("echo foo ; cat bar | ta reta", 24);
-        List<List<List<String>>> p = parser.program();
-        assertEquals(1, parser.c0);
-        assertEquals(1, parser.c1);
-        assertEquals(1, parser.c2);
-        assertEquals(0, parser.c3);
-    }
-
-    @Test
-    public void testCompleteOptions() throws Exception {
-        CommandSession session = new DummyCommandSession();
-        Completer comp = new ArgumentCompleter(session, new MyFunction(), "my:action");
-        assertEquals(Arrays.asList("--check", "--foo", "--help", "--integer", "--string", "-c", "-f","-i","-s"), complete(comp, "action -"));
-        assertEquals(Arrays.asList(), complete(comp, "action --foo "));
-        assertEquals(Arrays.asList("action "), complete(comp, "acti"));
-        assertEquals(Arrays.asList("my:action "), complete(comp, "my:ac"));
-        assertEquals(Arrays.asList("--foo "), complete(comp, "action --f"));
-        assertEquals(Arrays.asList("--help "), complete(comp, "action --h"));
-        assertEquals(Arrays.asList("-c "), complete(comp, "action -c"));
-        assertEquals(Arrays.asList("--check "), complete(comp, "action -f 2 --c"));
-        assertEquals(Arrays.asList("foo1 "), complete(comp, "action -f 2 --check foo1"));
-        assertEquals(Arrays.asList("bar1", "bar2"), complete(comp, "action -f 2 --check foo1 "));
-        assertEquals(Arrays.asList("one", "two"), complete(comp, "action -s "));
-        assertEquals(Arrays.asList("one", "two"), complete(comp, "action --string "));
-        assertEquals(Arrays.asList("two "), complete(comp, "action -s t"));
-        assertEquals(Arrays.asList("1", "2"), complete(comp, "action -i "));
-        assertEquals(Arrays.asList("1", "2"), complete(comp, "action --integer "));
-        assertEquals(Arrays.asList("2 "), complete(comp, "action -i 2"));
-    }
-
-    public static class MyFunction extends SimpleCommand implements CompletableFunction {
-        public MyFunction() {
-            super(MyAction.class);
-        }
-        public List<Completer> getCompleters() {
-            return Arrays.<Completer>asList(
-                    new StringsCompleter(Arrays.asList("foo1", "foo2")),
-                    new StringsCompleter(Arrays.asList("bar1", "bar2"))
-            );
-        }
-
-        public Map<String,Completer> getOptionalCompleters() {
-            Map<String,Completer> completers = new HashMap<String,Completer>();
-            completers.put("-s",new StringsCompleter(Arrays.asList("one","two")));
-            completers.put("--integer",new StringsCompleter(Arrays.asList("1","2")));
-            return completers;
-        }
-    }
-
-    public static class MyAction implements Action {
-        @Option(name = "-f", aliases = { "--foo" })
-        int f;
-
-        @Option(name = "-c", aliases = "--check")
-        boolean check;
-
-        @Option(name = "-s", aliases = "--string")
-        String string;
-
-        @Option(name = "-i", aliases = "--integer")
-        String integer;
-
-        public Object execute(CommandSession session) throws Exception {
-            return null;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/completer/BooleanCompleterTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/BooleanCompleterTest.java b/shell/console/src/test/java/org/apache/karaf/shell/console/completer/BooleanCompleterTest.java
deleted file mode 100644
index 7cbf05c..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/BooleanCompleterTest.java
+++ /dev/null
@@ -1,62 +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.console.completer;
-
-import org.apache.karaf.shell.commands.Action;
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.basic.SimpleCommand;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.karaf.shell.console.Completer;
-import org.junit.Test;
-
-import java.util.Arrays;
-
-import static org.junit.Assert.assertEquals;
-
-public class BooleanCompleterTest extends CompleterTestSupport {
-
-    @Test
-    public void testCompleteArgumnets() throws Exception {
-        CommandSession session = new DummyCommandSession();
-        Completer comp = new ArgumentCompleter(session, new SimpleCommand(MyAction.class), "my:action");
-
-        // arg 0
-        assertEquals(Arrays.asList("true "), complete(comp, "action t"));
-        assertEquals(Arrays.asList("false "), complete(comp, "action f"));
-
-        // arg 1
-        assertEquals(Arrays.asList("true "), complete(comp, "action false t"));
-        assertEquals(Arrays.asList("false "), complete(comp, "action true f"));
-
-        // unknown args
-        assertEquals(Arrays.asList(), complete(comp, "action c"));
-        assertEquals(Arrays.asList(), complete(comp, "action true true a"));
-    }
-
-    public static class MyAction implements Action {
-        @Argument(index = 0)
-        Boolean foo;
-        @Argument(index = 1)
-        boolean bar;
-
-        public Object execute(CommandSession session) throws Exception {
-            return null;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompleterTestSupport.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompleterTestSupport.java b/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompleterTestSupport.java
deleted file mode 100644
index e5341a5..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompleterTestSupport.java
+++ /dev/null
@@ -1,34 +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.console.completer;
-
-import org.apache.karaf.shell.console.Completer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Useful base class for completion related test cases
- */
-public abstract class CompleterTestSupport {
-    protected List<String> complete(Completer completer, String buf) {
-        List<String> candidates = new ArrayList<String>();
-        completer.complete(buf, buf.length(), candidates);
-        return candidates;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompleterValuesTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompleterValuesTest.java b/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompleterValuesTest.java
deleted file mode 100644
index 2ec4a81..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompleterValuesTest.java
+++ /dev/null
@@ -1,74 +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.console.completer;
-
-import org.apache.karaf.shell.commands.Action;
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.CompleterValues;
-import org.apache.karaf.shell.commands.basic.SimpleCommand;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.karaf.shell.console.Completer;
-import org.junit.Test;
-
-import java.util.Arrays;
-import java.util.List;
-
-import static org.junit.Assert.assertEquals;
-
-public class CompleterValuesTest extends CompleterTestSupport {
-
-    @Test
-    public void testCompleteArgumnets() throws Exception {
-        CommandSession session = new DummyCommandSession();
-        Completer comp = new ArgumentCompleter(session, new SimpleCommand(MyAction.class), "my:action");
-
-        // arg 0
-        assertEquals(Arrays.asList("a1", "a2", "a3"), complete(comp, "action a"));
-        assertEquals(Arrays.asList("b4", "b5"), complete(comp, "action b"));
-
-        // arg 1
-        assertEquals(Arrays.asList("c2", "c3"), complete(comp, "action a1 c"));
-        assertEquals(Arrays.asList("d5", "d6", "d7"), complete(comp, "action b4 d"));
-
-        // unknown args
-        assertEquals(Arrays.asList(), complete(comp, "action c"));
-        assertEquals(Arrays.asList(), complete(comp, "action a1 d5 a"));
-    }
-
-    public static class MyAction implements Action {
-        @Argument(index = 0)
-        String foo;
-        @Argument(index = 1)
-        String bar;
-
-        public Object execute(CommandSession session) throws Exception {
-            return null;
-        }
-
-        @CompleterValues(index = 0)
-        public String[] getFooValues() {
-            return new String[]{"a1", "a2", "a3", "b4", "b5"};
-        }
-
-        @CompleterValues(index = 1)
-        public List<String> getBarValues() {
-            return Arrays.asList("c2", "c3", "d5", "d6", "d7");
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompletionTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompletionTest.java b/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompletionTest.java
deleted file mode 100644
index 25d0485..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/CompletionTest.java
+++ /dev/null
@@ -1,172 +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.console.completer;
-
-import java.util.Arrays;
-
-import org.apache.felix.service.command.CommandSession;
-import org.apache.karaf.shell.commands.Action;
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.Option;
-import org.apache.karaf.shell.commands.basic.Context;
-import org.apache.karaf.shell.commands.basic.SimpleCommand;
-import org.apache.karaf.shell.commands.basic.SimpleSubShell;
-import org.apache.karaf.shell.console.CommandSessionHolder;
-import org.apache.karaf.shell.console.Completer;
-import org.apache.karaf.shell.console.ExitAction;
-import org.apache.karaf.shell.console.SessionProperties;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class CompletionTest extends CompleterTestSupport {
-
-    @Test
-    public void testSubShellCompletion() throws Exception {
-        Context context = new Context();
-        context.set("SCOPE", "*");
-        context.set(SessionProperties.COMPLETION_MODE, "subshell");
-        CommandSessionHolder.setSession(context.getSession());
-
-        context.addCommand("*", new SimpleSubShell("foo"), "foo");
-        context.addCommand("*", new SimpleCommand(ExitAction.class), "exit");
-        context.addCommand("foo", new SimpleCommand(MyAction.class), "my-action");
-        context.addCommand("foo", new SimpleCommand(MyActionTwoArguments.class), "one-action");
-        context.addCommand("bar", new SimpleCommand(MyAction.class), "one-action");
-        context.addCommand("bar", new SimpleCommand(MyActionTwoArguments.class), "another");
-
-        Completer comp = new CommandsCompleter(context.getSession());
-
-        context.execute("foo");
-        assertEquals(Arrays.asList("my-action "), complete(comp, "my"));
-        assertEquals(Arrays.asList("exit ", "my-action ", "one-action "), complete(comp, ""));
-        assertEquals(Arrays.asList(), complete(comp, "an"));
-        assertEquals(Arrays.asList("--check", "--foo", "--help", "--integer", "--string"),
-                     complete(comp, "my-action --"));
-        assertEquals(Arrays.asList("--dummy", "--help"), complete(comp, "one-action --"));
-
-        context.execute("exit");
-        assertEquals(Arrays.asList(), complete(comp, "my"));
-        assertEquals(Arrays.asList("exit ", "foo "), complete(comp, ""));
-        assertEquals(Arrays.asList(), complete(comp, "an"));
-    }
-
-    @Test
-    public void testFirstCompletion() throws Exception {
-        Context context = new Context();
-        context.set("SCOPE", "*");
-        context.set(SessionProperties.COMPLETION_MODE, "first");
-        CommandSessionHolder.setSession(context.getSession());
-
-        context.addCommand("*", new SimpleSubShell("foo"), "foo");
-        context.addCommand("*", new SimpleCommand(ExitAction.class), "exit");
-        context.addCommand("foo", new SimpleCommand(MyAction.class), "my-action");
-        context.addCommand("foo", new SimpleCommand(MyActionTwoArguments.class), "one-action");
-        context.addCommand("bar", new SimpleCommand(MyAction.class), "one-action");
-        context.addCommand("bar", new SimpleCommand(MyActionTwoArguments.class), "another");
-
-        Completer comp = new CommandsCompleter(context.getSession());
-
-        context.execute("foo");
-        assertEquals(Arrays.asList("my-action "), complete(comp, "my"));
-        assertEquals(Arrays.asList("my-action ", "one-action "), complete(comp, ""));
-        assertEquals(Arrays.asList("another "), complete(comp, "an"));
-        assertEquals(Arrays.asList("--check", "--foo", "--help", "--integer", "--string"),
-                     complete(comp, "my-action --"));
-        assertEquals(Arrays.asList("--dummy", "--help"), complete(comp, "one-action --"));
-
-        context.execute("exit");
-        assertEquals(Arrays.asList("my-action "), complete(comp, "my"));
-        assertEquals(Arrays.asList("*:exit", "*:foo", "another", "bar:another",
-                                   "bar:one-action", "exit", "foo",
-                                   "foo:my-action", "foo:one-action", "my-action",
-                                   "one-action", "one-action"), complete(comp, ""));
-        assertEquals(Arrays.asList("another "), complete(comp, "an"));
-    }
-
-    @Test
-    public void testGlobalCompletion() throws Exception {
-        Context context = new Context();
-        context.set("SCOPE", "*");
-        context.set(SessionProperties.COMPLETION_MODE, "global");
-        CommandSessionHolder.setSession(context.getSession());
-
-        context.addCommand("*", new SimpleSubShell("foo"), "foo");
-        context.addCommand("*", new SimpleCommand(ExitAction.class), "exit");
-        context.addCommand("foo", new SimpleCommand(MyAction.class), "my-action");
-        context.addCommand("foo", new SimpleCommand(MyActionTwoArguments.class), "one-action");
-        context.addCommand("bar", new SimpleCommand(MyAction.class), "one-action");
-        context.addCommand("bar", new SimpleCommand(MyActionTwoArguments.class), "another");
-
-        Completer comp = new CommandsCompleter(context.getSession());
-
-        context.execute("foo");
-        assertEquals(Arrays.asList("my-action "), complete(comp, "my"));
-        assertEquals(Arrays.asList("*:exit", "*:foo", "another", "bar:another",
-                                    "bar:one-action", "exit", "foo",
-                                   "foo:my-action", "foo:one-action", "my-action",
-                                   "one-action", "one-action"), complete(comp, ""));
-        assertEquals(Arrays.asList("another "), complete(comp, "an"));
-        assertEquals(Arrays.asList("--check", "--foo", "--help", "--integer", "--string"),
-                     complete(comp, "my-action --"));
-        assertEquals(Arrays.asList("--dummy", "--help"), complete(comp, "one-action --"));
-
-        context.execute("exit");
-        assertEquals(Arrays.asList("my-action "), complete(comp, "my"));
-        assertEquals(Arrays.asList("*:exit", "*:foo", "another", "bar:another",
-                                   "bar:one-action", "exit", "foo",
-                                   "foo:my-action", "foo:one-action", "my-action",
-                                   "one-action", "one-action"), complete(comp, ""));
-        assertEquals(Arrays.asList("another "), complete(comp, "an"));
-    }
-
-    public static class MyAction implements Action {
-        @Option(name = "-f", aliases = { "--foo" })
-        int f;
-
-        @Option(name = "-c", aliases = "--check")
-        boolean check;
-
-        @Option(name = "-s", aliases = "--string")
-        String string;
-
-        @Option(name = "-i", aliases = "--integer")
-        String integer;
-
-        public Object execute(CommandSession session) throws Exception {
-            return null;
-        }
-    }
-
-    public static class MyActionTwoArguments implements Action {
-
-        @Option(name = "--dummy")
-        boolean dummy;
-
-        @Argument(index = 0, name = "one", description = "one description", required = true, multiValued = false)
-        private String one;
-
-        @Argument(index = 1, name = "two", description = "two description", required = true, multiValued = false)
-        private String two;
-
-        public Object execute(CommandSession session) throws Exception {
-            return null;
-        }
-
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/completer/DummyCommandSession.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/DummyCommandSession.java b/shell/console/src/test/java/org/apache/karaf/shell/console/completer/DummyCommandSession.java
deleted file mode 100644
index ac1a894..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/DummyCommandSession.java
+++ /dev/null
@@ -1,48 +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.console.completer;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-
-import org.apache.felix.service.command.CommandSession;
-
-public class DummyCommandSession implements CommandSession {
-    public Object convert(Class<?> type, Object instance) {
-        return null;
-    }
-    public CharSequence format(Object target, int level) {
-        return null;
-    }
-    public void put(String name, Object value) {
-    }
-    public Object get(String name) {
-        return null;
-    }
-    public PrintStream getConsole() {
-        return null;
-    }
-    public InputStream getKeyboard() {
-        return null;
-    }
-    public void close() {
-    }
-    public Object execute(CharSequence commandline) throws Exception {
-        return null;
-    }
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/completer/FileCompleterTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/FileCompleterTest.java b/shell/console/src/test/java/org/apache/karaf/shell/console/completer/FileCompleterTest.java
deleted file mode 100644
index 0405371..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/completer/FileCompleterTest.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.console.completer;
-
-import java.io.File;
-import java.util.Arrays;
-
-import org.apache.karaf.shell.commands.Action;
-import org.apache.karaf.shell.commands.Argument;
-import org.apache.karaf.shell.commands.basic.SimpleCommand;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.karaf.shell.console.Completer;
-import org.junit.Test;
-
-import static org.junit.Assert.assertEquals;
-
-public class FileCompleterTest extends CompleterTestSupport {
-
-    @Test
-    public void testCompleteArgumnets() throws Exception {
-        CommandSession session = new DummyCommandSession();
-        Completer comp = new ArgumentCompleter(session, new SimpleCommand(MyAction.class), "my:action");
-
-        // arg 0
-        assertEquals(Arrays.asList("src"+File.separator), complete(comp, "action s"));
-        assertEquals(Arrays.asList("main"+File.separator), complete(comp, "action src/m"));
-        assertEquals(Arrays.asList("java"+File.separator), complete(comp, "action src/main/j"));
-    }
-
-    public static class MyAction implements Action {
-        @Argument(index = 0)
-        File foo;
-        @Argument(index = 1)
-        File bar;
-
-        public Object execute(CommandSession session) throws Exception {
-            return null;
-        }
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/impl/ExampleSubclassMain.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/impl/ExampleSubclassMain.java b/shell/console/src/test/java/org/apache/karaf/shell/console/impl/ExampleSubclassMain.java
deleted file mode 100644
index 6a3f8b2..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/impl/ExampleSubclassMain.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.console.impl;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-
-import jline.Terminal;
-import org.apache.felix.gogo.runtime.CommandProcessorImpl;
-import org.apache.felix.service.threadio.ThreadIO;
-import org.apache.karaf.shell.console.impl.Main;
-import org.apache.karaf.shell.console.impl.jline.ConsoleImpl;
-
-import java.util.Properties;
-
-/**
- * This class is mostly here so that folks can see an example of how you can extend the Karaf Main shell.  Also
- * lets Karaf developers see how changes the Main class can affect the interface comparability
- * with sub classes.
- */
-public class ExampleSubclassMain extends Main  {
-
-    public static void main(String args[]) throws Exception {
-        ExampleSubclassMain main = new ExampleSubclassMain();
-        main.run(args);
-    }
-
-    public void ExampleSubclassMain() {
-        // Sets the name of the shell and the current user.
-        setApplication("example");
-        setUser("unknown");
-    }
-
-    @Override
-    protected ConsoleImpl createConsole(CommandProcessorImpl commandProcessor, ThreadIO threadIO, InputStream in, PrintStream out, PrintStream err, Terminal terminal) throws Exception {
-        return new ConsoleImpl(commandProcessor, threadIO, in, out, err, terminal, null, null, null, true) {
-
-            /**
-             * If you don't overwrite, then karaf will use the welcome message found in the
-             * following resource files:
-             * <ul>
-             *   <li>org/apache/karaf/shell/console/branding.properties</li>
-             *   <li>org/apache/karaf/branding/branding.properties</li>
-             * <ul>
-             */
-            @Override
-            protected void welcome(Properties brandingProps) {
-                session.getConsole().println("===============================================");
-                session.getConsole().println(" Example Shell ");
-                session.getConsole().println("===============================================");
-            }
-
-            /**
-             * If you don't overwrite then Karaf builds a prompt based on the current app and user.
-             * @return
-             */
-            @Override
-            protected String getPrompt() {
-                return "example>";
-            }
-
-            /**
-             * If you don't overwrite, then karaf automatically adds session properties
-             * found in the following resource files:
-             * <ul>
-             *   <li>org/apache/karaf/shell/console/branding.properties</li>
-             *   <li>org/apache/karaf/branding/branding.properties</li>
-             * <ul>
-             */
-            @Override
-            protected void setSessionProperties(Properties brandingProps) {
-                // we won't add any session properties.
-            }
-
-        };
-    }
-
-    /**
-     * if you don't override, then Karaf will discover the commands listed in the
-     * "META-INF/services/org/apache/karaf/shell/commands" resource file.
-     *
-     * @return
-     */
-    @Override
-    public String getDiscoveryResource() {
-        return "META-INF/services/org/example/commands.index";
-    }
-
-
-}

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/console/impl/jline/ConsoleImplTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/console/impl/jline/ConsoleImplTest.java b/shell/console/src/test/java/org/apache/karaf/shell/console/impl/jline/ConsoleImplTest.java
deleted file mode 100644
index 24b229b..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/console/impl/jline/ConsoleImplTest.java
+++ /dev/null
@@ -1,195 +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.console.impl.jline;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertSame;
-import static org.junit.Assert.assertTrue;
-
-import java.io.InputStream;
-import java.io.PrintStream;
-import java.security.PrivilegedAction;
-
-import javax.security.auth.Subject;
-
-import org.apache.felix.gogo.api.CommandSessionListener;
-import org.apache.felix.gogo.runtime.threadio.ThreadIOImpl;
-import org.apache.felix.service.command.CommandProcessor;
-import org.apache.felix.service.command.CommandSession;
-import org.apache.felix.service.command.Converter;
-import org.apache.karaf.jaas.boot.principal.RolePrincipal;
-import org.apache.karaf.shell.console.impl.jline.ConsoleImpl.DelegateSession;
-import org.apache.karaf.shell.security.impl.SecuredCommandProcessorImpl;
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
-import org.junit.Test;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Filter;
-import org.osgi.framework.FrameworkUtil;
-import org.osgi.framework.ServiceListener;
-import org.osgi.framework.ServiceReference;
-
-public class ConsoleImplTest {
-    @Test
-    public void testConsoleImpl() throws Exception {
-        ServiceReference<?> cmRef = EasyMock.createMock(ServiceReference.class);
-        EasyMock.expect(cmRef.getProperty(CommandProcessor.COMMAND_SCOPE)).andReturn("myscope").anyTimes();
-        EasyMock.expect(cmRef.getProperty(CommandProcessor.COMMAND_FUNCTION)).andReturn("myfunction").anyTimes();
-        EasyMock.replay(cmRef);
-        ServiceReference<?>[] cmRefs = new ServiceReference[] {cmRef};
-
-        BundleContext bc = EasyMock.createMock(BundleContext.class);
-        EasyMock.expect(bc.getServiceReference((Class<?>) EasyMock.anyObject())).andReturn(null).anyTimes();
-        EasyMock.expect(bc.getService((ServiceReference<?>) EasyMock.anyObject())).andReturn(null).anyTimes();
-        bc.addServiceListener(EasyMock.isA(ServiceListener.class), EasyMock.isA(String.class));
-        EasyMock.expectLastCall().anyTimes();
-        EasyMock.expect(bc.getServiceReferences((String) null,
-                "(&(osgi.command.scope=*)(osgi.command.function=*)" +
-                        "(|(org.apache.karaf.service.guard.roles=myrole)(!(org.apache.karaf.service.guard.roles=*))))")).andReturn(cmRefs).anyTimes();
-        EasyMock.expect(bc.getServiceReferences(Converter.class.getName(), null)).andReturn(null).anyTimes();
-        EasyMock.expect(bc.getServiceReferences(CommandSessionListener.class.getName(), null)).andReturn(null).anyTimes();
-        EasyMock.expect(bc.createFilter(EasyMock.isA(String.class))).andAnswer(new IAnswer<Filter>() {
-            @Override
-            public Filter answer() throws Throwable {
-                return FrameworkUtil.createFilter((String) EasyMock.getCurrentArguments()[0]);
-            }
-        }).anyTimes();
-        EasyMock.replay(bc);
-
-        final ConsoleImpl console = new ConsoleImpl(null, new ThreadIOImpl(), System.in, System.out, System.err, null, "UTF-8", null, bc, true);
-        assertTrue(console.session instanceof DelegateSession);
-
-        console.session.put("foo", "bar");
-
-        final DelegateSession ds = (DelegateSession) console.session;
-        assertNull("Precondition", ds.delegate);
-
-        Subject subject = new Subject();
-        subject.getPrincipals().add(new RolePrincipal("myrole"));
-
-        Subject.doAs(subject, new PrivilegedAction<Object>() {
-            @Override
-            public Object run() {
-                SecuredCommandProcessorImpl secCP = console.createSecuredCommandProcessor();
-                assertNotNull(ds.delegate);
-                assertEquals("Attributes set before the delegate was set should have been transferred",
-                        "bar", ds.get("foo"));
-                assertEquals("Attributes set before the delegate was set should have been transferred",
-                        "bar", ds.delegate.get("foo"));
-                assertSame(System.out, ds.delegate.getConsole());
-                assertSame(System.out, ds.getConsole());
-
-                assertTrue(secCP.getCommands().contains("myscope:myfunction"));
-
-                return null;
-            }
-        });
-    }
-
-    @Test
-    public void testDelegateSession() throws Exception {
-        DelegateSession ds = new DelegateSession();
-
-        ds.put("a", "b");
-        assertEquals("b", ds.get("a"));
-
-        TestSession ts = new TestSession();
-
-        assertNull("Precondition", ts.lastInvoked);
-
-        ds.setDelegate(ts);
-        assertEquals("put(a,b)", ts.lastInvoked);
-
-        ds.put("c", "d");
-        assertEquals("put(c,d)", ts.lastInvoked);
-
-        ds.execute("hello 1234");
-        assertEquals("execute(hello 1234)", ts.lastInvoked);
-
-        ds.close();
-        assertEquals("close", ts.lastInvoked);
-
-        ds.getKeyboard();
-        assertEquals("getKeyboard", ts.lastInvoked);
-
-        ds.getConsole();
-        assertEquals("getConsole", ts.lastInvoked);
-
-        ds.get("xyz");
-        assertEquals("get(xyz)", ts.lastInvoked);
-
-        ds.format("foo", 12);
-        assertEquals("format(foo,12)", ts.lastInvoked);
-
-        ds.convert(TestSession.class, "a string");
-        assertEquals("convert(TestSession,a string)", ts.lastInvoked);
-    }
-
-    static class TestSession implements CommandSession {
-        String lastInvoked;
-
-        @Override
-        public Object execute(CharSequence commandline) throws Exception {
-            lastInvoked = "execute(" + commandline + ")";
-            return null;
-        }
-
-        @Override
-        public void close() {
-            lastInvoked = "close";
-        }
-
-        @Override
-        public InputStream getKeyboard() {
-            lastInvoked = "getKeyboard";
-            return null;
-        }
-
-        @Override
-        public PrintStream getConsole() {
-            lastInvoked = "getConsole";
-            return null;
-        }
-
-        @Override
-        public Object get(String name) {
-            lastInvoked = "get(" + name + ")";
-            return null;
-        }
-
-        @Override
-        public void put(String name, Object value) {
-            lastInvoked = "put(" + name + "," + value + ")";
-        }
-
-        @Override
-        public CharSequence format(Object target, int level) {
-            lastInvoked = "format(" + target + "," + level + ")";
-            return null;
-        }
-
-        @Override
-        public Object convert(Class<?> type, Object instance) {
-            lastInvoked = "convert(" + type.getSimpleName() + "," + instance + ")";
-            return null;
-        }
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/karaf/blob/b4ae5245/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandConfigTransformerTest.java
----------------------------------------------------------------------
diff --git a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandConfigTransformerTest.java b/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandConfigTransformerTest.java
deleted file mode 100644
index 8900258..0000000
--- a/shell/console/src/test/java/org/apache/karaf/shell/security/impl/SecuredCommandConfigTransformerTest.java
+++ /dev/null
@@ -1,281 +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.security.impl;
-
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
-import static org.junit.Assert.fail;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Dictionary;
-import java.util.HashMap;
-import java.util.Hashtable;
-import java.util.List;
-import java.util.Map;
-
-import org.easymock.EasyMock;
-import org.easymock.IAnswer;
-import org.junit.Test;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceReference;
-import org.osgi.service.cm.Configuration;
-import org.osgi.service.cm.ConfigurationAdmin;
-import org.osgi.service.cm.ConfigurationEvent;
-
-public class SecuredCommandConfigTransformerTest {
-
-    @Test
-    public void testTransformation() throws Exception {
-        Dictionary<String, Object> props = new Hashtable<String, Object>();
-        props.put("foo", "a,b,c");
-        props.put("bar[/.*[a]+*/]", "d");
-        props.put("bar", "e");
-        props.put("zar[/.*HiThere*/]", "f");
-        props.put("service.pid", SecuredCommandConfigTransformer.PROXY_COMMAND_ACL_PID_PREFIX + "abc");
-        Configuration commandConfig = mockConfiguration(props);
-
-        Dictionary<String, Object> props2 = new Hashtable<String, Object>();
-        props2.put("xxx", "yyy");
-        props2.put("service.pid", SecuredCommandConfigTransformer.PROXY_COMMAND_ACL_PID_PREFIX + "xyz.123");
-        Configuration commandConfig2 = mockConfiguration(props2);
-
-        Dictionary<String, Object> props3 = new Hashtable<String, Object>();
-        props3.put("test", "toast");
-        props3.put("service.pid", "xyz.123");
-        Configuration otherConfig = mockConfiguration(props3);
-
-        final Map<String, Configuration> configurations = new HashMap<String, Configuration>();
-
-        ConfigurationAdmin ca = EasyMock.createMock(ConfigurationAdmin.class);
-        EasyMock.expect(ca.listConfigurations(
-                "(service.pid=" + SecuredCommandConfigTransformer.PROXY_COMMAND_ACL_PID_PREFIX + "*)")).
-                andReturn(new Configuration [] {commandConfig, commandConfig2, otherConfig}).anyTimes();
-        EasyMock.expect(ca.getConfiguration(EasyMock.isA(String.class), EasyMock.anyString())).andAnswer(new IAnswer<Configuration>() {
-            @Override
-            public Configuration answer() throws Throwable {
-                String pid = (String) EasyMock.getCurrentArguments()[0];
-                Configuration c = configurations.get(pid);
-                if (c == null) {
-                    c = EasyMock.createMock(Configuration.class);
-
-                    // Put some expectations in the various mocks
-                    Dictionary<String, Object> m = new Hashtable<String, Object>();
-                    if ("org.apache.karaf.service.acl.command.abc.foo".equals(pid)) {
-                        m.put("service.guard", "(&(osgi.command.scope=abc)(osgi.command.function=foo))");
-                        m.put("execute", "a,b,c");
-                        m.put("foo", "a,b,c");
-                    } else if ("org.apache.karaf.service.acl.command.abc.bar".equals(pid)) {
-                        m.put("service.guard", "(&(osgi.command.scope=abc)(osgi.command.function=bar))");
-                        m.put("execute[/.*/,/.*[a]+*/]", "d");
-                        m.put("execute", "e");
-                        m.put("bar[/.*[a]+*/]", "d");
-                        m.put("bar", "e");
-                    } else if ("org.apache.karaf.service.acl.command.abc.zar".equals(pid)) {
-                        m.put("service.guard", "(&(osgi.command.scope=abc)(osgi.command.function=zar))");
-                        m.put("execute[/.*/,/.*HiThere*/]", "f");
-                        m.put("zar[/.*HiThere*/]", "f");
-                    } else {
-                        fail("Unexpected PID: " + pid);
-                    }
-                    m.put("*", "*");
-                    c.update(m);
-                    EasyMock.expectLastCall().once();
-
-                    EasyMock.replay(c);
-                    configurations.put(pid, c);
-                }
-                return c;
-            }
-        }).anyTimes();
-        EasyMock.replay(ca);
-
-        SecuredCommandConfigTransformer scct = new SecuredCommandConfigTransformer();
-        scct.setConfigAdmin(ca);
-        scct.init();
-
-        assertEquals(3, configurations.size());
-
-        boolean foundFoo = false;
-        boolean foundBar = false;
-        boolean foundZar = false;
-        for (Map.Entry<String, Configuration> entry : configurations.entrySet()) {
-            Configuration c = entry.getValue();
-            EasyMock.verify(c);
-            if ("org.apache.karaf.service.acl.command.abc.foo".equals(entry.getKey())) {
-                foundFoo = true;
-            } else if ("org.apache.karaf.service.acl.command.abc.bar".equals(entry.getKey())) {
-                foundBar = true;
-            } else if ("org.apache.karaf.service.acl.command.abc.zar".equals(entry.getKey())) {
-                foundZar = true;
-            }
-        }
-
-        assertTrue(foundFoo);
-        assertTrue(foundBar);
-        assertTrue(foundZar);
-
-    }
-
-    Configuration mockConfiguration(Dictionary<String, Object> props) {
-        Configuration commandConfig = EasyMock.createMock(Configuration.class);
-        EasyMock.expect(commandConfig.getPid()).
-                andReturn((String) props.get(Constants.SERVICE_PID)).anyTimes();
-        EasyMock.expect(commandConfig.getProperties()).andReturn(props).anyTimes();
-        EasyMock.replay(commandConfig);
-        return commandConfig;
-    }
-
-    @Test
-    public void testConfigurationEventAdded() throws Exception {
-        String testPid = SecuredCommandConfigTransformer.PROXY_COMMAND_ACL_PID_PREFIX + "test123";
-        Configuration conf = EasyMock.createMock(Configuration.class);
-        EasyMock.expect(conf.getPid()).andReturn(testPid).anyTimes();
-        EasyMock.replay(conf);
-
-        ConfigurationAdmin cm = EasyMock.createMock(ConfigurationAdmin.class);
-        EasyMock.expect(cm.listConfigurations(EasyMock.isA(String.class))).andReturn(null).anyTimes();
-        EasyMock.expect(cm.getConfiguration(testPid, null)).andReturn(conf).anyTimes();
-        EasyMock.replay(cm);
-
-        final List<String> generateCalled = new ArrayList<String>();
-        SecuredCommandConfigTransformer scct = new SecuredCommandConfigTransformer() {
-            @Override
-            void generateServiceGuardConfig(Configuration config) throws IOException {
-                generateCalled.add(config.getPid());
-            }
-        };
-        scct.setConfigAdmin(cm);
-        scct.init();
-
-        @SuppressWarnings("unchecked")
-        ServiceReference<ConfigurationAdmin> cmRef = EasyMock.createMock(ServiceReference.class);
-        EasyMock.expect(cmRef.getBundle()).andReturn(null).anyTimes();
-        EasyMock.replay(cmRef);
-
-        ConfigurationEvent event = new ConfigurationEvent(cmRef, ConfigurationEvent.CM_UPDATED, null, testPid);
-        
-
-        assertEquals("Precondition", 0, generateCalled.size());
-        scct.configurationEvent(event);
-        assertEquals(1, generateCalled.size());
-        assertEquals(testPid, generateCalled.iterator().next());
-    }
-
-    @Test
-    public void testConfigurationEventAddedNonCommand() throws Exception {
-        ConfigurationAdmin cm = EasyMock.createMock(ConfigurationAdmin.class);
-        EasyMock.expect(cm.listConfigurations(EasyMock.isA(String.class))).andReturn(null).anyTimes();
-        EasyMock.replay(cm);
-
-        SecuredCommandConfigTransformer scct = new SecuredCommandConfigTransformer();
-        scct.setConfigAdmin(cm);
-        scct.init();
-
-        @SuppressWarnings("unchecked")
-        ServiceReference<ConfigurationAdmin> cmRef = EasyMock.createMock(ServiceReference.class);
-        EasyMock.replay(cmRef);
-        ConfigurationEvent event = new ConfigurationEvent(cmRef, ConfigurationEvent.CM_UPDATED, null, "test123");
-
-        scct.configurationEvent(event);
-        EasyMock.verify(cm); // Ensure that this doesn't cause any unwanted calls on ConfigAdmin
-    }
-
-    @Test
-    public void testConfigurationEventDeleted() throws Exception {
-        String testPid = SecuredCommandConfigTransformer.PROXY_COMMAND_ACL_PID_PREFIX + "test123";
-
-        ConfigurationAdmin cm = EasyMock.createMock(ConfigurationAdmin.class);
-        EasyMock.expect(cm.listConfigurations(EasyMock.isA(String.class))).andReturn(null).anyTimes();
-        EasyMock.replay(cm);
-
-        SecuredCommandConfigTransformer scct = new SecuredCommandConfigTransformer();
-        scct.setConfigAdmin(cm);
-        scct.init();
-
-        @SuppressWarnings("unchecked")
-        ServiceReference<ConfigurationAdmin> cmRef = EasyMock.createMock(ServiceReference.class);
-        EasyMock.replay(cmRef);
-        ConfigurationEvent event = new ConfigurationEvent(cmRef, ConfigurationEvent.CM_DELETED, null, testPid);
-
-        Configuration c1 = EasyMock.createMock(Configuration.class);
-        c1.delete();
-        EasyMock.expectLastCall().once();
-        EasyMock.replay(c1);
-        Configuration c2 = EasyMock.createMock(Configuration.class);
-        c2.delete();
-        EasyMock.expectLastCall().once();
-        EasyMock.replay(c2);
-
-        EasyMock.reset(cm);
-        EasyMock.expect(cm.listConfigurations("(service.pid=org.apache.karaf.service.acl.command.test123.*)")).
-                andReturn(new Configuration[] {c1, c2}).once();
-        EasyMock.replay(cm);
-
-        scct.configurationEvent(event);
-
-        EasyMock.verify(cm);
-        EasyMock.verify(c1);
-        EasyMock.verify(c2);
-    }
-
-    @Test
-    public void testConfigurationEventDeletedNonScope() throws Exception {
-        String testPid = SecuredCommandConfigTransformer.PROXY_COMMAND_ACL_PID_PREFIX + "abc.def";
-
-        ConfigurationAdmin cm = EasyMock.createMock(ConfigurationAdmin.class);
-        EasyMock.expect(cm.listConfigurations(EasyMock.isA(String.class))).andReturn(null).anyTimes();
-        EasyMock.replay(cm);
-
-        SecuredCommandConfigTransformer scct = new SecuredCommandConfigTransformer();
-        scct.setConfigAdmin(cm);
-        scct.init();
-
-        @SuppressWarnings("unchecked")
-        ServiceReference<ConfigurationAdmin> cmRef = EasyMock.createMock(ServiceReference.class);
-        EasyMock.replay(cmRef);
-        ConfigurationEvent event = new ConfigurationEvent(cmRef, ConfigurationEvent.CM_DELETED, null, testPid);
-
-        EasyMock.reset(cm);
-        // Do not expect any further calls to cm...
-        EasyMock.replay(cm);
-
-        scct.configurationEvent(event);
-        EasyMock.verify(cm);
-    }
-
-    @Test
-    public void testConfigurationLocationChangedEventNoEffect() throws Exception {
-        String testPid = SecuredCommandConfigTransformer.PROXY_COMMAND_ACL_PID_PREFIX + "test123";
-
-        ConfigurationAdmin cm = EasyMock.createMock(ConfigurationAdmin.class);
-        EasyMock.expect(cm.listConfigurations(EasyMock.isA(String.class))).andReturn(null).anyTimes();
-        EasyMock.replay(cm);
-
-        SecuredCommandConfigTransformer scct = new SecuredCommandConfigTransformer();
-        scct.setConfigAdmin(cm);
-        scct.init();
-
-        @SuppressWarnings("unchecked")
-        ServiceReference<ConfigurationAdmin> cmRef = EasyMock.createMock(ServiceReference.class);
-        EasyMock.replay(cmRef);
-        ConfigurationEvent event = new ConfigurationEvent(cmRef, ConfigurationEvent.CM_LOCATION_CHANGED, null, testPid);
-
-        scct.configurationEvent(event);
-        EasyMock.verify(cm); // Ensure that this doesn't cause any unwanted calls on ConfigAdmin
-    }
-}