Skip to content

Commit

Permalink
Improve the message when a provider cannot be used by doing an early …
Browse files Browse the repository at this point in the history
…check and restore compatibility with Jansi 1.17 (#906, fixes #904)
  • Loading branch information
gnodet authored Dec 21, 2023
1 parent c275b40 commit af7777d
Show file tree
Hide file tree
Showing 7 changed files with 96 additions and 72 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import java.util.regex.Pattern;

import org.fusesource.jansi.AnsiConsole;
import org.fusesource.jansi.internal.Kernel32;
import org.jline.terminal.Attributes;
import org.jline.terminal.Size;
import org.jline.terminal.Terminal;
Expand Down Expand Up @@ -79,6 +80,20 @@ public static boolean isAtLeast(int major, int minor) {
return JANSI_MAJOR_VERSION > major || JANSI_MAJOR_VERSION == major && JANSI_MINOR_VERSION >= minor;
}

public static void verifyAtLeast(int major, int minor) {
if (!isAtLeast(major, minor)) {
throw new UnsupportedOperationException("An old version of Jansi is loaded from "
+ Kernel32.class
.getClassLoader()
.getResource(Kernel32.class.getName().replace('.', '/') + ".class"));
}
}

public JansiTerminalProvider() {
verifyAtLeast(1, 17);
checkIsSystemStream(SystemStream.Output);
}

@Override
public String name() {
return TerminalBuilder.PROP_PROVIDER_JANSI;
Expand All @@ -93,29 +108,29 @@ public Pty current(SystemStream systemStream) throws IOException {
} else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
// Solaris is not supported by jansi
// return SolarisNativePty.current();
throw new UnsupportedOperationException("Unsupported platform " + osName);
} else if (osName.startsWith("FreeBSD")) {
if (isAtLeast(1, 16)) {
return FreeBsdNativePty.current(this, systemStream);
}
return FreeBsdNativePty.current(this, systemStream);
} else {
throw new UnsupportedOperationException("Unsupported platform " + osName);
}
throw new UnsupportedOperationException();
}

public Pty open(Attributes attributes, Size size) throws IOException {
if (isAtLeast(1, 16)) {
String osName = System.getProperty("os.name");
if (osName.startsWith("Linux")) {
return LinuxNativePty.open(this, attributes, size);
} else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) {
return OsXNativePty.open(this, attributes, size);
} else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
// Solaris is not supported by jansi
// return SolarisNativePty.current();
} else if (osName.startsWith("FreeBSD")) {
return FreeBsdNativePty.open(this, attributes, size);
}
String osName = System.getProperty("os.name");
if (osName.startsWith("Linux")) {
return LinuxNativePty.open(this, attributes, size);
} else if (osName.startsWith("Mac") || osName.startsWith("Darwin")) {
return OsXNativePty.open(this, attributes, size);
} else if (osName.startsWith("Solaris") || osName.startsWith("SunOS")) {
// Solaris is not supported by jansi
// return SolarisNativePty.current();
throw new UnsupportedOperationException("Unsupported platform " + osName);
} else if (osName.startsWith("FreeBSD")) {
return FreeBsdNativePty.open(this, attributes, size);
} else {
throw new UnsupportedOperationException("Unsupported platform " + osName);
}
throw new UnsupportedOperationException();
}

@Override
Expand Down Expand Up @@ -148,15 +163,10 @@ public Terminal winSysTerminal(
boolean paused,
SystemStream systemStream)
throws IOException {
if (isAtLeast(1, 12)) {
JansiWinSysTerminal terminal = JansiWinSysTerminal.createTerminal(
this, systemStream, name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused);
if (!isAtLeast(1, 16)) {
terminal.disableScrolling();
}
return terminal;
}
throw new UnsupportedOperationException();
JansiWinSysTerminal terminal = JansiWinSysTerminal.createTerminal(
this, systemStream, name, type, ansiPassThrough, encoding, nativeSignals, signalHandler, paused);
terminal.disableScrolling();
return terminal;
}

public Terminal posixSysTerminal(
Expand Down Expand Up @@ -192,22 +202,18 @@ public Terminal newTerminal(
@Override
public boolean isSystemStream(SystemStream stream) {
try {
if (OSUtils.IS_WINDOWS) {
return isWindowsSystemStream(stream);
} else {
return isPosixSystemStream(stream);
}
return checkIsSystemStream(stream);
} catch (Throwable t) {
return false;
}
}

public boolean isWindowsSystemStream(SystemStream stream) {
return JansiWinSysTerminal.isWindowsSystemStream(stream);
}

public boolean isPosixSystemStream(SystemStream stream) {
return JansiNativePty.isPosixSystemStream(stream);
private boolean checkIsSystemStream(SystemStream stream) {
if (OSUtils.IS_WINDOWS) {
return JansiWinSysTerminal.isWindowsSystemStream(stream);
} else {
return JansiNativePty.isPosixSystemStream(stream);
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

import java.io.IOException;

import org.fusesource.jansi.internal.Kernel32;
import org.jline.terminal.impl.AbstractWindowsConsoleWriter;

import static org.fusesource.jansi.internal.Kernel32.WriteConsoleW;
import static org.jline.terminal.impl.jansi.win.WindowsSupport.getLastErrorMessage;

class JansiWinConsoleWriter extends AbstractWindowsConsoleWriter {

Expand All @@ -27,7 +27,7 @@ public JansiWinConsoleWriter(long console) {
@Override
protected void writeConsole(char[] text, int len) throws IOException {
if (WriteConsoleW(console, text, len, writtenChars, 0) == 0) {
throw new IOException("Failed to write to console: " + Kernel32.getLastErrorMessage());
throw new IOException("Failed to write to console: " + getLastErrorMessage());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
import java.io.IOException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.util.function.IntConsumer;

import org.fusesource.jansi.internal.Kernel32;
Expand All @@ -28,17 +27,15 @@
import org.jline.utils.InfoCmp;
import org.jline.utils.OSUtils;

import static org.fusesource.jansi.internal.Kernel32.FORMAT_MESSAGE_FROM_SYSTEM;
import static org.fusesource.jansi.internal.Kernel32.FormatMessageW;
import static org.fusesource.jansi.internal.Kernel32.GetConsoleScreenBufferInfo;
import static org.fusesource.jansi.internal.Kernel32.GetLastError;
import static org.fusesource.jansi.internal.Kernel32.GetStdHandle;
import static org.fusesource.jansi.internal.Kernel32.INVALID_HANDLE_VALUE;
import static org.fusesource.jansi.internal.Kernel32.STD_ERROR_HANDLE;
import static org.fusesource.jansi.internal.Kernel32.STD_INPUT_HANDLE;
import static org.fusesource.jansi.internal.Kernel32.STD_OUTPUT_HANDLE;
import static org.fusesource.jansi.internal.Kernel32.WaitForSingleObject;
import static org.fusesource.jansi.internal.Kernel32.readConsoleInputHelper;
import static org.jline.terminal.impl.jansi.win.WindowsSupport.getLastErrorMessage;

public class JansiWinSysTerminal extends AbstractWindowsTerminal<Long> {

Expand Down Expand Up @@ -294,16 +291,4 @@ public void disableScrolling() {
strings.remove(InfoCmp.Capability.delete_line);
strings.remove(InfoCmp.Capability.parm_delete_line);
}

static String getLastErrorMessage() {
int errorCode = GetLastError();
return getErrorMessage(errorCode);
}

static String getErrorMessage(int errorCode) {
int bufferSize = 160;
byte[] data = new byte[bufferSize];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, bufferSize, null);
return new String(data, StandardCharsets.UTF_16LE).trim();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
import java.io.IOException;
import java.io.Writer;

import org.fusesource.jansi.internal.Kernel32;
import org.jline.utils.AnsiWriter;
import org.jline.utils.Colors;

import static org.fusesource.jansi.internal.Kernel32.*;
import static org.jline.terminal.impl.jansi.win.WindowsSupport.getLastErrorMessage;

/**
* A Windows ANSI escape processor, that uses JNA to access native platform
Expand Down Expand Up @@ -81,7 +81,7 @@ public WindowsAnsiWriter(Writer out) throws IOException {
private void getConsoleInfo() throws IOException {
out.flush();
if (GetConsoleScreenBufferInfo(console, info) == 0) {
throw new IOException("Could not get the screen info: " + Kernel32.getLastErrorMessage());
throw new IOException("Could not get the screen info: " + getLastErrorMessage());
}
if (negative) {
info.attributes = invertAttributeColors(info.attributes);
Expand All @@ -103,7 +103,7 @@ private void applyAttribute() throws IOException {
attributes = invertAttributeColors(attributes);
}
if (SetConsoleTextAttribute(console, attributes) == 0) {
throw new IOException(Kernel32.getLastErrorMessage());
throw new IOException(getLastErrorMessage());
}
}

Expand All @@ -121,7 +121,7 @@ private void applyCursorPosition() throws IOException {
info.cursorPosition.x = (short) Math.max(0, Math.min(info.size.x - 1, info.cursorPosition.x));
info.cursorPosition.y = (short) Math.max(0, Math.min(info.size.y - 1, info.cursorPosition.y));
if (SetConsoleCursorPosition(console, info.cursorPosition.copy()) == 0) {
throw new IOException(Kernel32.getLastErrorMessage());
throw new IOException(getLastErrorMessage());
}
}

Expand Down Expand Up @@ -359,7 +359,7 @@ protected void processInsertLine(int optionInt) throws IOException {
info.attributes = originalColors;
info.unicodeChar = ' ';
if (ScrollConsoleScreenBuffer(console, scroll, scroll, org, info) == 0) {
throw new IOException(Kernel32.getLastErrorMessage());
throw new IOException(getLastErrorMessage());
}
}

Expand All @@ -375,7 +375,7 @@ protected void processDeleteLine(int optionInt) throws IOException {
info.attributes = originalColors;
info.unicodeChar = ' ';
if (ScrollConsoleScreenBuffer(console, scroll, scroll, org, info) == 0) {
throw new IOException(Kernel32.getLastErrorMessage());
throw new IOException(getLastErrorMessage());
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* Copyright (c) 2023, the original author(s).
*
* This software is distributable under the BSD license. See the terms of the
* BSD license in the documentation provided with this software.
*
* https://opensource.org/licenses/BSD-3-Clause
*/
package org.jline.terminal.impl.jansi.win;

import java.nio.charset.StandardCharsets;

import static org.fusesource.jansi.internal.Kernel32.FORMAT_MESSAGE_FROM_SYSTEM;
import static org.fusesource.jansi.internal.Kernel32.FormatMessageW;
import static org.fusesource.jansi.internal.Kernel32.GetLastError;

class WindowsSupport {

public static String getLastErrorMessage() {
int errorCode = GetLastError();
int bufferSize = 160;
byte[] data = new byte[bufferSize];
FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, 0, errorCode, 0, data, bufferSize, null);
return new String(data, StandardCharsets.UTF_16LE).trim();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,9 @@ public static String posixSystemStreamName(SystemStream stream) {

private static boolean isatty(int fd) {
if (Platform.isMac()) {
if (Platform.is64Bit() && Platform.isARM()) {
throw new UnsupportedOperationException("Unsupported platform mac-aarch64");
}
return OsXNativePty.isatty(fd) == 1;
} else if (Platform.isLinux()) {
return LinuxNativePty.isatty(fd) == 1;
Expand All @@ -204,6 +207,9 @@ private static boolean isatty(int fd) {

private static String ttyname(int fd) {
if (Platform.isMac()) {
if (Platform.is64Bit() && Platform.isARM()) {
throw new UnsupportedOperationException("Unsupported platform mac-aarch64");
}
return OsXNativePty.ttyname(fd);
} else if (Platform.isLinux()) {
return LinuxNativePty.ttyname(fd);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@
import org.jline.utils.OSUtils;

public class JnaTerminalProvider implements TerminalProvider {

public JnaTerminalProvider() {
checkSystemStream(SystemStream.Output);
}

@Override
public String name() {
return TerminalBuilder.PROP_PROVIDER_JNA;
Expand Down Expand Up @@ -106,22 +111,18 @@ public Terminal newTerminal(
@Override
public boolean isSystemStream(SystemStream stream) {
try {
if (OSUtils.IS_WINDOWS) {
return isWindowsSystemStream(stream);
} else {
return isPosixSystemStream(stream);
}
return checkSystemStream(stream);
} catch (Throwable t) {
return false;
}
}

public boolean isWindowsSystemStream(SystemStream stream) {
return JnaWinSysTerminal.isWindowsSystemStream(stream);
}

public boolean isPosixSystemStream(SystemStream stream) {
return JnaNativePty.isPosixSystemStream(stream);
private boolean checkSystemStream(SystemStream stream) {
if (OSUtils.IS_WINDOWS) {
return JnaWinSysTerminal.isWindowsSystemStream(stream);
} else {
return JnaNativePty.isPosixSystemStream(stream);
}
}

@Override
Expand Down

0 comments on commit af7777d

Please sign in to comment.