Skip to content

Commit 43767fc

Browse files
committed
Support static native images
1 parent 9d60bc5 commit 43767fc

12 files changed

Lines changed: 301 additions & 48 deletions

src/main/java/org/fusesource/jansi/AnsiConsole.java

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525
import java.nio.charset.Charset;
2626
import java.nio.charset.UnsupportedCharsetException;
2727

28-
import org.fusesource.jansi.internal.MingwSupport;
2928
import org.fusesource.jansi.internal.OSInfo;
29+
import org.fusesource.jansi.internal.stty.Stty;
3030
import org.fusesource.jansi.io.AnsiOutputStream;
3131
import org.fusesource.jansi.io.AnsiProcessor;
3232
import org.fusesource.jansi.io.FastBufferedOutputStream;
@@ -173,6 +173,22 @@ public class AnsiConsole {
173173
* The name of the {@code ffm} provider.
174174
*/
175175
public static final String JANSI_PROVIDER_FFM = "ffm";
176+
/**
177+
* The name of the {@code stty} provider.
178+
*/
179+
public static final String JANSI_PROVIDER_STTY = "stty";
180+
181+
/**
182+
* The name of the {@code native-image} provider.
183+
* <p>This provider uses the
184+
* <a href="https://www.graalvm.org/latest/reference-manual/native-image/native-code-interoperability/C-API/">Native Image C API</a>
185+
* to call native functions, so it is only available when building to native image.
186+
* Additionally, this provider currently does not support Windows.
187+
* <p>Note: This is not the only provider available on Native Image,
188+
* and it is usually recommended to use ffm or jni provider.
189+
* This provider is mainly used when building static native images linked to musl libc.
190+
*/
191+
public static final String JANSI_PROVIDER_NATIVE_IMAGE = "native-image";
176192

177193
/**
178194
* @deprecated this field will be made private in a future release, use {@link #sysOut()} instead
@@ -306,10 +322,9 @@ private static AnsiPrintStream ansiStream(boolean stdout) {
306322
processor = null;
307323
type = AnsiType.Native;
308324
installer = uninstaller = null;
309-
MingwSupport mingw = new MingwSupport();
310-
String name = mingw.getConsoleName(stdout);
325+
String name = Stty.getConsoleName(stdout);
311326
if (name != null && !name.isEmpty()) {
312-
width = () -> mingw.getTerminalWidth(name);
327+
width = () -> Stty.getTerminalWidth(name);
313328
} else {
314329
width = () -> -1;
315330
}

src/main/java/org/fusesource/jansi/AnsiMain.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
import org.fusesource.jansi.internal.AnsiConsoleSupport;
3030
import org.fusesource.jansi.internal.AnsiConsoleSupportHolder;
3131
import org.fusesource.jansi.internal.JansiLoader;
32-
import org.fusesource.jansi.internal.MingwSupport;
32+
import org.fusesource.jansi.internal.stty.Stty;
3333

3434
import static java.nio.charset.StandardCharsets.UTF_8;
3535
import static org.fusesource.jansi.Ansi.ansi;
@@ -208,11 +208,10 @@ private static void diagnoseTty(boolean stderr) {
208208
long console = AnsiConsoleSupportHolder.getKernel32().getStdHandle(!stderr);
209209
isatty = AnsiConsoleSupportHolder.getKernel32().isTty(console);
210210
if ((AnsiConsole.IS_CONEMU || AnsiConsole.IS_CYGWIN || AnsiConsole.IS_MSYSTEM) && isatty == 0) {
211-
MingwSupport mingw = new MingwSupport();
212-
String name = mingw.getConsoleName(!stderr);
211+
String name = Stty.getConsoleName(!stderr);
213212
if (name != null && !name.isEmpty()) {
214213
isatty = 1;
215-
width = mingw.getTerminalWidth(name);
214+
width = Stty.getTerminalWidth(name);
216215
} else {
217216
isatty = 0;
218217
width = 0;

src/main/java/org/fusesource/jansi/internal/AnsiConsoleSupportHolder.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,11 +44,10 @@ private static AnsiConsoleSupport findProvider(String providerList) {
4444
RuntimeException error = null;
4545

4646
for (String provider : providers) {
47+
String className = "org.fusesource.jansi.internal." + provider.replace("-", "") + ".AnsiConsoleSupportImpl";
4748
try {
4849
return (AnsiConsoleSupport)
49-
Class.forName("org.fusesource.jansi.internal." + provider + ".AnsiConsoleSupportImpl")
50-
.getConstructor()
51-
.newInstance();
50+
Class.forName(className).getConstructor().newInstance();
5251
} catch (Throwable t) {
5352
if (error == null) {
5453
error = new RuntimeException("Unable to create AnsiConsoleSupport provider");

src/main/java/org/fusesource/jansi/internal/OSInfo.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,10 @@ public static boolean isWindows() {
135135
return System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("win");
136136
}
137137

138+
public static boolean isMacOS() {
139+
return System.getProperty("os.name").toLowerCase(Locale.ROOT).contains("mac");
140+
}
141+
138142
public static boolean isAndroid() {
139143
return System.getProperty("java.runtime.name", "")
140144
.toLowerCase(Locale.ROOT)

src/main/java/org/fusesource/jansi/internal/ffm/AnsiConsoleSupportImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import java.lang.foreign.MemorySegment;
2222
import java.lang.foreign.ValueLayout;
2323

24+
import org.fusesource.jansi.AnsiConsole;
2425
import org.fusesource.jansi.internal.AnsiConsoleSupport;
2526
import org.fusesource.jansi.internal.OSInfo;
2627
import org.fusesource.jansi.io.AnsiProcessor;
@@ -30,7 +31,7 @@
3031
public final class AnsiConsoleSupportImpl extends AnsiConsoleSupport {
3132

3233
public AnsiConsoleSupportImpl() {
33-
super("ffm");
34+
super(AnsiConsole.JANSI_PROVIDER_FFM);
3435
}
3536

3637
public AnsiConsoleSupportImpl(boolean checkNativeAccess) {

src/main/java/org/fusesource/jansi/internal/jni/AnsiConsoleSupportImpl.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import java.io.OutputStream;
2020
import java.nio.charset.StandardCharsets;
2121

22+
import org.fusesource.jansi.AnsiConsole;
2223
import org.fusesource.jansi.internal.AnsiConsoleSupport;
2324
import org.fusesource.jansi.io.AnsiProcessor;
2425
import org.fusesource.jansi.io.WindowsAnsiProcessor;
@@ -36,7 +37,7 @@
3637
public final class AnsiConsoleSupportImpl extends AnsiConsoleSupport {
3738

3839
public AnsiConsoleSupportImpl() {
39-
super("jni");
40+
super(AnsiConsole.JANSI_PROVIDER_JNI);
4041
}
4142

4243
@Override
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (C) 2009-2023 the original author(s).
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.fusesource.jansi.internal.nativeimage;
17+
18+
import org.fusesource.jansi.AnsiConsole;
19+
import org.fusesource.jansi.internal.AnsiConsoleSupport;
20+
import org.fusesource.jansi.internal.OSInfo;
21+
import org.fusesource.jansi.internal.stty.SttyCLibrary;
22+
import org.graalvm.nativeimage.c.type.CTypeConversion;
23+
24+
public final class AnsiConsoleSupportImpl extends AnsiConsoleSupport {
25+
26+
public AnsiConsoleSupportImpl() {
27+
super(AnsiConsole.JANSI_PROVIDER_NATIVE_IMAGE);
28+
29+
if (!OSInfo.isInImageCode()) {
30+
throw new UnsupportedOperationException("This provider is only available in native images");
31+
}
32+
33+
if (OSInfo.isWindows()) {
34+
throw new UnsupportedOperationException("This provider is currently unavailable on Windows");
35+
}
36+
}
37+
38+
@Override
39+
protected CLibrary createCLibrary() {
40+
String stdoutTty = CTypeConversion.toJavaString(PosixCLibrary.ttyname(CLibrary.STDOUT_FILENO));
41+
String stderrTty = CTypeConversion.toJavaString(PosixCLibrary.ttyname(CLibrary.STDERR_FILENO));
42+
43+
return new SttyCLibrary(stdoutTty, stderrTty) {
44+
@Override
45+
public int isTty(int fd) {
46+
return PosixCLibrary.isatty(fd);
47+
}
48+
};
49+
}
50+
51+
@Override
52+
protected Kernel32 createKernel32() {
53+
throw new UnsupportedOperationException();
54+
}
55+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright (C) 2009-2023 the original author(s).
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.fusesource.jansi.internal.nativeimage;
17+
18+
import org.graalvm.nativeimage.c.CContext;
19+
import org.graalvm.nativeimage.c.function.CFunction;
20+
import org.graalvm.nativeimage.c.type.CCharPointer;
21+
22+
@CContext(PosixDirectives.class)
23+
final class PosixCLibrary {
24+
@CFunction(transition = CFunction.Transition.NO_TRANSITION)
25+
public static native int isatty(int fd);
26+
27+
@CFunction(transition = CFunction.Transition.NO_TRANSITION)
28+
public static native CCharPointer ttyname(int fd);
29+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*
2+
* Copyright (C) 2009-2023 the original author(s).
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.fusesource.jansi.internal.nativeimage;
17+
18+
import org.graalvm.nativeimage.Platform;
19+
import org.graalvm.nativeimage.c.CContext;
20+
21+
public class PosixDirectives implements CContext.Directives {
22+
@Override
23+
public boolean isInConfiguration() {
24+
return Platform.includedIn(Platform.LINUX.class) || Platform.includedIn(Platform.MACOS.class);
25+
}
26+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Copyright (C) 2009-2023 the original author(s).
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package org.fusesource.jansi.internal.stty;
17+
18+
import org.fusesource.jansi.AnsiConsole;
19+
import org.fusesource.jansi.internal.AnsiConsoleSupport;
20+
21+
public final class AnsiConsoleSupportImpl extends AnsiConsoleSupport {
22+
public AnsiConsoleSupportImpl() {
23+
super(AnsiConsole.JANSI_PROVIDER_STTY);
24+
}
25+
26+
@Override
27+
protected CLibrary createCLibrary() {
28+
return new SttyCLibrary(Stty.getConsoleName(true), Stty.getConsoleName(false));
29+
}
30+
31+
@Override
32+
protected Kernel32 createKernel32() {
33+
throw new UnsupportedOperationException();
34+
}
35+
}

0 commit comments

Comments
 (0)