From 6480702b84e56b92ae9f7d81699c91ee86123f2c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 10 Apr 2024 23:15:12 +0530 Subject: [PATCH] fix(deps): update dependency org.fusesource.jansi:jansi to v2 (#13436) * fix(deps): update dependency org.fusesource.jansi:jansi to v2 * fix(ansi): remove the usages of deprecated methods Use `AnsiConsole.systemInstall()` and `AnsiConsole.systemUninstall()`. * fix(grailsconsole): bind system out and err stream --------- Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Co-authored-by: Puneet Behl --- gradle.properties | 2 +- .../grails/build/logging/GrailsConsole.java | 159 ++++++++---------- .../build/logging/GrailsEclipseConsole.java | 21 +-- .../AnsiConsoleUrlMappingsRendererSpec.groovy | 67 ++++---- 4 files changed, 104 insertions(+), 145 deletions(-) diff --git a/gradle.properties b/gradle.properties index 1b85188497c..1376e0d7c40 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,7 +16,7 @@ h2.version=2.2.224 h2Version=2.2.224 hibernateDatastoreVersion=8.0.2 jakartaAnnotationApiVersion=2.0.0 -jansiVersion=1.18 +jansiVersion=2.4.1 javaParserCoreVersion=3.25.9 javaxAnnotationApiVersion=1.3.2 jaxbApiVersion=2.3.1 diff --git a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java index f77eec47701..36b53306720 100644 --- a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java +++ b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsConsole.java @@ -15,18 +15,7 @@ */ package grails.build.logging; -import static org.fusesource.jansi.Ansi.ansi; -import static org.fusesource.jansi.Ansi.Color.DEFAULT; -import static org.fusesource.jansi.Ansi.Color.RED; -import static org.fusesource.jansi.Ansi.Color.YELLOW; -import static org.fusesource.jansi.Ansi.Erase.FORWARD; import grails.util.Environment; - -import java.io.*; -import java.util.Collection; -import java.util.List; -import java.util.Stack; - import jline.Terminal; import jline.TerminalFactory; import jline.UnixTerminal; @@ -37,17 +26,25 @@ import jline.internal.Log; import jline.internal.ShutdownHooks; import jline.internal.TerminalLineSettings; - import org.apache.tools.ant.BuildException; -import org.grails.build.interactive.CandidateListCompletionHandler; -import org.grails.build.logging.GrailsConsoleErrorPrintStream; -import org.grails.build.logging.GrailsConsolePrintStream; import org.codehaus.groovy.runtime.DefaultGroovyMethods; import org.codehaus.groovy.runtime.StackTraceUtils; import org.codehaus.groovy.runtime.typehandling.NumberMath; import org.fusesource.jansi.Ansi; import org.fusesource.jansi.Ansi.Color; import org.fusesource.jansi.AnsiConsole; +import org.grails.build.interactive.CandidateListCompletionHandler; +import org.grails.build.logging.GrailsConsoleErrorPrintStream; +import org.grails.build.logging.GrailsConsolePrintStream; + +import java.io.*; +import java.util.Collection; +import java.util.List; +import java.util.Stack; + +import static org.fusesource.jansi.Ansi.Color.*; +import static org.fusesource.jansi.Ansi.Erase.FORWARD; +import static org.fusesource.jansi.Ansi.ansi; /** * Utility class for delivering console output in a nicely formatted way. @@ -77,7 +74,7 @@ public class GrailsConsole implements ConsoleLogger { private int cursorMove; private Thread shutdownHookThread; private Character defaultInputMask = null; - + /** * Whether to enable verbose mode */ @@ -120,7 +117,7 @@ public class GrailsConsole implements ConsoleLogger { @Override public String toString() { if (size() == 1) return peek() + CATEGORY_SEPARATOR; - return DefaultGroovyMethods.join((Iterable)this, CATEGORY_SEPARATOR) + CATEGORY_SEPARATOR; + return DefaultGroovyMethods.join((Iterable) this, CATEGORY_SEPARATOR) + CATEGORY_SEPARATOR; } }; @@ -135,7 +132,7 @@ public String toString() { private boolean userInputActive; public void addShutdownHook() { - if( !Environment.isFork() ) { + if (!Environment.isFork()) { shutdownHookThread = new Thread(new Runnable() { @Override public void run() { @@ -145,14 +142,14 @@ public void run() { Runtime.getRuntime().addShutdownHook(shutdownHookThread); } } - + public void removeShutdownHook() { - if(shutdownHookThread != null) { + if (shutdownHookThread != null) { Runtime.getRuntime().removeShutdownHook(shutdownHookThread); } } - - + + protected GrailsConsole() throws IOException { cursorMove = 1; @@ -162,13 +159,14 @@ protected GrailsConsole() throws IOException { maxIndicatorString = new StringBuilder(indicator).append(indicator).append(indicator).append(indicator).append(indicator); } - + /** * Use in testing when System.out, System.err or System.in change + * * @throws IOException */ public void reinitialize(InputStream systemIn, PrintStream systemOut, PrintStream systemErr) throws IOException { - if(reader != null) { + if (reader != null) { reader.shutdown(); } initialize(systemIn, systemOut, systemErr); @@ -180,7 +178,7 @@ protected void initialize(InputStream systemIn, PrintStream systemOut, PrintStre redirectSystemOutAndErr(true); System.setProperty(ShutdownHooks.JLINE_SHUTDOWNHOOK, "false"); - + if (isInteractiveEnabled()) { reader = createConsoleReader(systemIn); reader.setBellEnabled(false); @@ -193,38 +191,28 @@ protected void initialize(InputStream systemIn, PrintStream systemOut, PrintStre if (history != null) { reader.setHistory(history); } - } - else if (isActivateTerminal()) { + } else if (isActivateTerminal()) { terminal = createTerminal(); } } protected void bindSystemOutAndErr(PrintStream systemOut, PrintStream systemErr) { originalSystemOut = unwrapPrintStream(systemOut); - out = wrapInPrintStream(originalSystemOut); + out = originalSystemOut; originalSystemErr = unwrapPrintStream(systemErr); - err = wrapInPrintStream(originalSystemErr); + err = originalSystemErr; } - + private PrintStream unwrapPrintStream(PrintStream printStream) { - if(printStream instanceof GrailsConsolePrintStream) { - return ((GrailsConsolePrintStream)printStream).getTargetOut(); + if (printStream instanceof GrailsConsolePrintStream) { + return ((GrailsConsolePrintStream) printStream).getTargetOut(); } - if(printStream instanceof GrailsConsoleErrorPrintStream) { - return ((GrailsConsoleErrorPrintStream)printStream).getTargetOut(); + if (printStream instanceof GrailsConsoleErrorPrintStream) { + return ((GrailsConsoleErrorPrintStream) printStream).getTargetOut(); } return printStream; } - private PrintStream wrapInPrintStream(PrintStream printStream) { - OutputStream ansiWrapped = ansiWrap(printStream); - if(ansiWrapped instanceof PrintStream) { - return (PrintStream)ansiWrapped; - } else { - return new PrintStream(ansiWrapped, true); - } - } - public PrintStream getErr() { return err; } @@ -271,7 +259,7 @@ protected ConsoleReader createConsoleReader(InputStream systemIn) throws IOExcep */ protected Terminal createTerminal() { terminal = TerminalFactory.create(); - if(isWindows()) { + if (isWindows()) { terminal.setEchoEnabled(true); } return terminal; @@ -279,7 +267,7 @@ protected Terminal createTerminal() { public void resetCompleters() { final ConsoleReader reader = getReader(); - if(reader != null) { + if (reader != null) { Collection completers = reader.getCompleters(); for (Completer completer : completers) { reader.removeCompleter(completer); @@ -292,6 +280,7 @@ public void resetCompleters() { } } } + /** * Prepares a history file to be used by the ConsoleReader. This file * will live in the home directory of the user. @@ -301,24 +290,13 @@ protected History prepareHistory() throws IOException { if (!file.exists()) { try { file.createNewFile(); - } - catch (IOException ignored) { + } catch (IOException ignored) { // can't create the file, so no history for you } } return file.canWrite() ? new FileHistory(file) : null; } - /** - * Hook method that allows controlling whether or not output streams should be wrapped by - * AnsiConsole.wrapOutputStream. Unfortunately, Eclipse consoles will look to the AnsiWrap - * like they do not understand ansi, even if we were to implement support in Eclipse to' - * handle it and the wrapped stream will not pass the ansi chars on to Eclipse). - */ - protected OutputStream ansiWrap(OutputStream out) { - return AnsiConsole.wrapOutputStream(out); - } - public boolean isWindows() { return System.getProperty("os.name").toLowerCase().indexOf("windows") != -1; } @@ -327,20 +305,23 @@ public static synchronized GrailsConsole getInstance() { if (instance == null) { try { final GrailsConsole console = createInstance(); + AnsiConsole.systemInstall(); console.addShutdownHook(); setInstance(console); } catch (IOException e) { throw new RuntimeException("Cannot create grails console: " + e.getMessage(), e); + } finally { + AnsiConsole.systemUninstall(); } } return instance; } - + public static synchronized void removeInstance() { if (instance != null) { instance.removeShutdownHook(); instance.restoreOriginalSystemOutAndErr(); - if(instance.getReader() != null) { + if (instance.getReader() != null) { instance.getReader().shutdown(); } instance = null; @@ -358,7 +339,7 @@ protected void restoreTerminal() { } catch (Exception e) { // ignore } - if(terminal instanceof UnixTerminal) { + if (terminal instanceof UnixTerminal) { // workaround for GRAILS-11494 try { new TerminalLineSettings().set("sane"); @@ -369,11 +350,10 @@ protected void restoreTerminal() { } protected void persistHistory() { - if(history instanceof Flushable) { + if (history instanceof Flushable) { try { - ((Flushable)history).flush(); - } - catch (Throwable e) { + ((Flushable) history).flush(); + } catch (Throwable e) { // ignore exception } } @@ -388,7 +368,7 @@ protected void redirectSystemOutAndErr(boolean force) { if (force || !(System.out instanceof GrailsConsolePrintStream)) { System.setOut(new GrailsConsolePrintStream(out)); } - if (force || !(System.err instanceof GrailsConsoleErrorPrintStream )) { + if (force || !(System.err instanceof GrailsConsoleErrorPrintStream)) { System.setErr(new GrailsConsoleErrorPrintStream(err)); } } @@ -438,7 +418,6 @@ public boolean isVerbose() { } /** - * * @return Whether to show stack traces */ public boolean isStacktrace() { @@ -508,8 +487,7 @@ public void indicateProgress() { updateStatus(lastMessage + indicator); } } - } - else { + } else { out.print(indicator); } } @@ -525,7 +503,7 @@ public void indicateProgress(int number, int total) { progressIndicatorActive = true; String currMsg = lastMessage; try { - updateStatus(currMsg + ' '+ number + " of " + total); + updateStatus(currMsg + ' ' + number + " of " + total); } finally { lastMessage = currMsg; } @@ -548,8 +526,7 @@ public void indicateProgressPercentage(long number, long total) { if (!isAnsiEnabled()) { out.print(".."); out.print(percentage + '%'); - } - else { + } else { updateStatus(currMsg + ' ' + percentage + '%'); } } finally { @@ -570,8 +547,7 @@ public void indicateProgress(int number) { try { if (isAnsiEnabled()) { updateStatus(currMsg + ' ' + number); - } - else { + } else { out.print(".."); out.print(number); } @@ -621,9 +597,9 @@ private void outputMessage(String msg, int replaceCount) { } private Ansi moveDownToSkipPrompt() { - return ansi() - .cursorDown(1) - .cursorLeft(PROMPT.length()); + return ansi() + .cursorDown(1) + .cursorLeft(PROMPT.length()); } private void postPrintMessage() { @@ -691,17 +667,16 @@ public boolean isAnsiEnabled() { /** * Use to log an error * - * @param msg The message + * @param msg The message * @param error The error */ @Override public void error(String msg, Throwable error) { try { - if ((verbose||stacktrace) && error != null) { + if ((verbose || stacktrace) && error != null) { printStackTrace(msg, error); error(ERROR, msg); - } - else { + } else { error(ERROR, msg + STACKTRACE_MESSAGE); } } finally { @@ -752,8 +727,7 @@ public void log(String msg) { } if (msg.endsWith(LINE_SEPARATOR)) { printStream.print(msg); - } - else { + } else { printStream.println(msg); } cursorMove = 0; @@ -785,8 +759,7 @@ public void append(String msg) { } if (msg.endsWith(LINE_SEPARATOR)) { printStream.print(msg); - } - else { + } else { printStream.println(msg); } cursorMove = 0; @@ -831,6 +804,7 @@ public void echoStatus() { * Replacement for AntBuilder.input() to eliminate dependency of * GrailsScriptRunner on the Ant libraries. Prints a message and * returns whatever the user enters (once they press <return>). + * * @param msg The message/question to display. * @return The line of text entered by the user. May be a blank * string. @@ -868,6 +842,7 @@ private String doUserInput(String msg, boolean secure) { /** * Shows the prompt to request user input + * * @param prompt The prompt to use * @return The user input prompt */ @@ -898,6 +873,7 @@ private String readLine(String prompt, boolean secure) { /** * Shows the prompt to request user input + * * @return The user input prompt */ public String showPrompt() { @@ -927,9 +903,10 @@ public String userInput(String message, List validResponses) { * displayed again and the method waits for more input. It will * display the message a maximum of three times before it gives up * and returns null. - * @param message The message/question to display. + * + * @param message The message/question to display. * @param validResponses An array of responses that the user is - * allowed to enter. Displayed after the message. + * allowed to enter. Displayed after the message. * @return The line of text entered by the user, or null * if the user never entered a valid string. */ @@ -1001,16 +978,14 @@ public void error(String label, String message) { cursorMove = 0; try { if (isAnsiEnabled()) { - Ansi ansi = outputErrorLabel(userInputActive ? moveDownToSkipPrompt() : ansi(), label).a(message).reset(); + Ansi ansi = outputErrorLabel(userInputActive ? moveDownToSkipPrompt() : ansi(), label).a(message).reset(); if (message.endsWith(LINE_SEPARATOR)) { out.print(ansi); - } - else { + } else { out.println(ansi); } - } - else { + } else { out.print(label); out.print(" "); logSimpleError(message); @@ -1024,7 +999,7 @@ private void verifySystemOut() { // something bad may have overridden the system out redirectSystemOutAndErr(false); } - + public void restoreOriginalSystemOutAndErr() { System.setOut(originalSystemOut); System.setErr(originalSystemErr); diff --git a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsEclipseConsole.java b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsEclipseConsole.java index ca42c6d81cc..5f69165ded5 100644 --- a/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsEclipseConsole.java +++ b/grails-bootstrap/src/main/groovy/grails/build/logging/GrailsEclipseConsole.java @@ -15,12 +15,11 @@ */ package grails.build.logging; -import java.io.IOException; -import java.io.OutputStream; - import jline.Terminal; import jline.UnsupportedTerminal; +import java.io.IOException; + /** * This class is meant to keep changes made in support of Eclipse separate from * the standard GrailsConsole implementation. @@ -54,22 +53,6 @@ public GrailsEclipseConsole() throws IOException { super(); } - @Override - protected OutputStream ansiWrap(OutputStream out) { - if (DEBUG) { - try { - out.write(("<<<"+ECLIPSE_SUPPORTS_ANSI_PROP+":"+eclipseSupportsAnsi()+">>>\n").getBytes("UTF-8")); - } catch (IOException e) { - } - } - //This method is called from the super constructor so eclipseSupportsAnsi field - //must be lazy initialised (it can't be initialised before we get called!) - if (eclipseSupportsAnsi()) { - return out; // expose unfiltered output to eclipse - } - return super.ansiWrap(out); - } - private boolean eclipseSupportsAnsi() { if (eclipseSupportsAnsi == null) { eclipseSupportsAnsi = boolProp(ECLIPSE_SUPPORTS_ANSI_PROP); diff --git a/grails-web-url-mappings/src/test/groovy/org/grails/web/mapping/reporting/AnsiConsoleUrlMappingsRendererSpec.groovy b/grails-web-url-mappings/src/test/groovy/org/grails/web/mapping/reporting/AnsiConsoleUrlMappingsRendererSpec.groovy index bfecdef1675..03c155fab32 100644 --- a/grails-web-url-mappings/src/test/groovy/org/grails/web/mapping/reporting/AnsiConsoleUrlMappingsRendererSpec.groovy +++ b/grails-web-url-mappings/src/test/groovy/org/grails/web/mapping/reporting/AnsiConsoleUrlMappingsRendererSpec.groovy @@ -13,26 +13,26 @@ import spock.lang.Specification /** * @author Graeme Rocher */ -class AnsiConsoleUrlMappingsRendererSpec extends Specification{ +class AnsiConsoleUrlMappingsRendererSpec extends Specification { void "Test render URL mappings for 3 level resource"() { - given:"A URL mappings renderer" - def sw = new ByteArrayOutputStream() - def ps = new PrintStream(sw) - def renderer = new AnsiConsoleUrlMappingsRenderer(ps) - renderer.isAnsiEnabled = false - def urlMappingsHolder = getUrlMappingsHolder { - "/books"(resources:'book') { - '/authors'(resources:'author') { - '/publisher'(resource:'publisher') - } + given: "A URL mappings renderer" + def sw = new ByteArrayOutputStream() + def ps = new PrintStream(sw) + def renderer = new AnsiConsoleUrlMappingsRenderer(ps) + renderer.isAnsiEnabled = false + def urlMappingsHolder = getUrlMappingsHolder { + "/books"(resources: 'book') { + '/authors'(resources: 'author') { + '/publisher'(resource: 'publisher') } } - when:"The URL mappings are rendered" - renderer.render(urlMappingsHolder.urlMappings.toList()) - println sw.toString() - then:"The output is correct" - sw.toString() == '''Controller: author + } + when: "The URL mappings are rendered" + renderer.render(urlMappingsHolder.urlMappings.toList()) + println sw.toString() + then: "The output is correct" + sw.toString() == '''Controller: author | GET | /books/${bookId}/authors/create | Action: create | | GET | /books/${bookId}/authors/${id}/edit | Action: edit | | POST | /books/${bookId}/authors | Action: save | @@ -65,25 +65,25 @@ Controller: publisher } void "Test render URL mappings to target stream"() { - given:"A URL mappings renderer" - def sw = new ByteArrayOutputStream() - def ps = new PrintStream(sw) - def renderer = new AnsiConsoleUrlMappingsRenderer(ps) - renderer.isAnsiEnabled = false - def urlMappingsHolder = getUrlMappingsHolder { - "/$controller/$action?/$id?(.$format)?"() - "/images/$name**.jpg"(controller:"image") - "/foo"(resources:"foo") - "500"(controller:"errors") - "/"(view:"/index") + given: "A URL mappings renderer" + def sw = new ByteArrayOutputStream() + def ps = new PrintStream(sw) + def renderer = new AnsiConsoleUrlMappingsRenderer(ps) + renderer.isAnsiEnabled = false + def urlMappingsHolder = getUrlMappingsHolder { + "/$controller/$action?/$id?(.$format)?"() + "/images/$name**.jpg"(controller: "image") + "/foo"(resources: "foo") + "500"(controller: "errors") + "/"(view: "/index") - } + } - when:"The URL mappings are rendered" - renderer.render(urlMappingsHolder.urlMappings.toList()) - println sw.toString() - then:"The output is correct" - sw.toString() == '''Dynamic Mappings + when: "The URL mappings are rendered" + renderer.render(urlMappingsHolder.urlMappings.toList()) + println sw.toString() + then: "The output is correct" + sw.toString() == '''Dynamic Mappings | * | / | View: /index | | * | /${controller}/${action}?/${id}?(.${format)? | Action: (default action) | @@ -105,6 +105,7 @@ Controller: image '''.denormalize() } + UrlMappingsHolder getUrlMappingsHolder(Closure mappings) { def ctx = new MockApplicationContext() ctx.registerMockBean(GrailsApplication.APPLICATION_ID, new DefaultGrailsApplication())