fusesource / jansi

Jansi is a small java library that allows you to use ANSI escape sequences to format your console output which works even on windows.
http://fusesource.github.io/jansi/
Apache License 2.0
1.12k stars 139 forks source link

Jansi 2.4.1 JPMS configuration regresses JLine #286

Open cdivilly opened 7 months ago

cdivilly commented 7 months ago

In Jansi 2.4.0 this is the JPMS configuration:

          <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <archive>
                        <manifestEntries>
                            <Automatic-Module-Name>org.fusesource.jansi</Automatic-Module-Name>
                        </manifestEntries>
                        <manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
                    </archive>
                </configuration>
            </plugin>

This makes JAnsi JPMS aware/enabled by giving it an Automatic Module Name. Jars with an automatic module name when loaded on the module path are treated as a JPMS module with the given name, with ALL packages in the jar exported.

This is the JPMS configuration in 2.4.1

            <plugin>
                <groupId>org.moditect</groupId>
                <artifactId>moditect-maven-plugin</artifactId>
                <version>1.0.0.Final</version>
                <executions>
                    <execution>
                        <id>add-module-infos</id>
                        <goals>
                            <goal>add-module-info</goal>
                        </goals>
                        <phase>package</phase>
                        <configuration>
                            <jvmVersion>9</jvmVersion>
                            <module>
                                <moduleInfo>
                                    <name>org.fusesource.jansi</name>
                                    <exports>org.fusesource.jansi;
                                        org.fusesource.jansi.io;</exports>
                                </moduleInfo>
                            </module>
                            <overwriteExistingFiles>true</overwriteExistingFiles>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

This generates a module-info.class instead of adding Automatic-Module-Name to the manifest. In this case only the following packages are exported from the org.fusesource.jansi module:

No other packages defined in JAnsi are visible to other modules. This regresses using JLine as a JPMS module because it is no longer able to access the package org.fusesource.jansi.internal which is used in the class JansiWinSysTerminal:

package org.jline.terminal.impl.jansi.win;

//...

import org.fusesource.jansi.internal.Kernel32;
import org.fusesource.jansi.internal.Kernel32.CONSOLE_SCREEN_BUFFER_INFO;
import org.fusesource.jansi.internal.Kernel32.INPUT_RECORD;
import org.fusesource.jansi.internal.Kernel32.KEY_EVENT_RECORD;

//...

import static org.fusesource.jansi.internal.Kernel32.GetConsoleScreenBufferInfo;
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;
//...
public class JansiWinSysTerminal extends AbstractWindowsTerminal<Long> {
//...

If you attempt to use JLine as a JPMS Module then you will get the following error:

Caused by: java.lang.ExceptionInInitializerError: Exception java.lang.IllegalAccessError: class org.jline.terminal.impl.jansi.win.JansiWinSysTerminal (in module org.jline) cannot access class org.fusesource.jansi.internal.Kernel32 (in module org.fusesource.jansi) because module org.fusesource.jansi does not export org.fusesource.jansi.internal to module org.jline [in thread "main"]

A short-term fix would be to roll back to the JPMS configuration of 2.4.0.

bowbahdoe commented 2 months ago

The right fix would be to either decide that yes, org.fusesource.jansi.internal is part of the public api and export it. Or to add a conditional export so that only jline can see it.