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:17 UTC
[2/6] karaf git commit: [KARAF-4570] Upgrade to JLine 3
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!");