groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pascalschumac...@apache.org
Subject incubator-groovy git commit: GROOVY-4888 - groovy console script execution output appears in all output windows (closes #160)
Date Sun, 25 Oct 2015 18:42:44 GMT
Repository: incubator-groovy
Updated Branches:
  refs/heads/GROOVY_2_4_X b85b0fdc4 -> bfb135e6c


GROOVY-4888 - groovy console script execution output appears in all output windows (closes
#160)


Project: http://git-wip-us.apache.org/repos/asf/incubator-groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-groovy/commit/bfb135e6
Tree: http://git-wip-us.apache.org/repos/asf/incubator-groovy/tree/bfb135e6
Diff: http://git-wip-us.apache.org/repos/asf/incubator-groovy/diff/bfb135e6

Branch: refs/heads/GROOVY_2_4_X
Commit: bfb135e6c46e34f50e11cc3de87bc990030a493c
Parents: b85b0fd
Author: John Wagenleitner <john.wagenleitner@gmail.com>
Authored: Sat Oct 24 23:30:34 2015 -0700
Committer: pascalschumacher <pascalschumacher@gmx.net>
Committed: Sun Oct 25 19:41:43 2015 +0100

----------------------------------------------------------------------
 .../src/main/groovy/groovy/ui/Console.groovy    | 44 ++++++++++++----
 .../groovy/ui/SystemOutputInterceptor.java      | 39 ++++++++++++--
 .../groovy/swing/SwingBuilderConsoleTest.groovy | 54 ++++++++++++++++++++
 3 files changed, 122 insertions(+), 15 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/bfb135e6/subprojects/groovy-console/src/main/groovy/groovy/ui/Console.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/ui/Console.groovy b/subprojects/groovy-console/src/main/groovy/groovy/ui/Console.groovy
index e7c5e44..2568e6b 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/ui/Console.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/ui/Console.groovy
@@ -853,42 +853,64 @@ options:
         updateFontSize(inputArea.font.size + 2)
     }
 
-    static boolean notifySystemOut(String str) {
+    static boolean notifySystemOut(int consoleId, String str) {
         if (!captureStdOut) {
             // Output as normal
             return true
         }
 
+        Closure doAppend = {
+            Console console = findConsoleById(consoleId)
+            if (console) {
+                console.appendOutputLines(str, console.outputStyle)
+            } else {
+                consoleControllers.each {it.appendOutputLines(str, it.outputStyle)}
+            }
+        }
+
         // Put onto GUI
         if (EventQueue.isDispatchThread()) {
-            consoleControllers.each {it.appendOutputLines(str, it.outputStyle)}
+            doAppend.call()
         }
         else {
-            SwingUtilities.invokeLater {
-                consoleControllers.each {it.appendOutputLines(str, it.outputStyle)}
-            }
+            SwingUtilities.invokeLater doAppend
         }
         return false
     }
 
-    static boolean notifySystemErr(String str) {
+    static boolean notifySystemErr(int consoleId, String str) {
         if (!captureStdErr) {
             // Output as normal
             return true
         }
 
+        Closure doAppend = {
+            Console console = findConsoleById(consoleId)
+            if (console) {
+                console.appendStacktrace(str)
+            } else {
+                consoleControllers.each {it.appendStacktrace(str)}
+            }
+        }
+
         // Put onto GUI
         if (EventQueue.isDispatchThread()) {
-            consoleControllers.each {it.appendStacktrace(str)}
+            doAppend.call()
         }
         else {
-            SwingUtilities.invokeLater {
-                consoleControllers.each {it.appendStacktrace(str)}
-            }
+            SwingUtilities.invokeLater doAppend
         }
         return false
     }
 
+    int getConsoleId() {
+        return System.identityHashCode(this)
+    }
+
+    private static Console findConsoleById(int consoleId) {
+        return consoleControllers.find { it.consoleId == consoleId }
+    }
+
     // actually run the script
 
     void runScript(EventObject evt = null) {
@@ -969,6 +991,7 @@ options:
         // Run in a thread outside of EDT, this method is usually called inside the EDT
         runThread = Thread.start {
             try {
+                systemOutInterceptor.setConsoleId(this.getConsoleId())
                 SwingUtilities.invokeLater { showExecutingMessage() }
                 String name = scriptFile?.name ?: (DEFAULT_SCRIPT_NAME_START + scriptNameCounter++)
                 if(beforeExecution) {
@@ -1003,6 +1026,7 @@ options:
                 runThread = null
                 scriptRunning = false
                 interruptAction.enabled = false
+                systemOutInterceptor.removeConsoleId()
             }
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/bfb135e6/subprojects/groovy-console/src/main/groovy/groovy/ui/SystemOutputInterceptor.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-console/src/main/groovy/groovy/ui/SystemOutputInterceptor.java
b/subprojects/groovy-console/src/main/groovy/groovy/ui/SystemOutputInterceptor.java
index 0df242b..7f47d8e 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/ui/SystemOutputInterceptor.java
+++ b/subprojects/groovy-console/src/main/groovy/groovy/ui/SystemOutputInterceptor.java
@@ -32,10 +32,18 @@ public class SystemOutputInterceptor extends FilterOutputStream {
     private Closure callback;
     private boolean output;
 
+    private static final ThreadLocal<Integer> consoleId = new ThreadLocal<Integer>()
{
+        @Override
+        protected Integer initialValue() {
+            return Integer.valueOf(0);
+        }
+    };
+
     /**
      * Constructor
      *
-     * @param callback accepts a string to be sent to std out and returns a Boolean.
+     * @param callback accepts the id of the target Console instance and a
+     *                 string to be sent to std out and returns a Boolean.
      *                 If the return value is true, output will be sent to
      *                 System.out, otherwise it will not.
      */
@@ -46,7 +54,8 @@ public class SystemOutputInterceptor extends FilterOutputStream {
     /**
      * Constructor
      *
-     * @param callback accepts a string to be sent to std out and returns a Boolean.
+     * @param callback accepts the id of the target Console instance and a
+     *                 string to be sent to std out and returns a Boolean.
      *                 If the return value is true, output will be sent to
      *                 System.out/System.err, otherwise it will not.
      * @param output   flag that tells whether System.out needs capturing ot System.err
@@ -84,10 +93,10 @@ public class SystemOutputInterceptor extends FilterOutputStream {
     }
 
     /**
-     * Intercepts output - moret common case of byte[]
+     * Intercepts output - more common case of byte[]
      */
     public void write(byte[] b, int off, int len) throws IOException {
-        Boolean result = (Boolean) callback.call(new String(b, off, len));
+        Boolean result = (Boolean) callback.call(consoleId.get().intValue(), new String(b,
off, len));
         if (result) {
             out.write(b, off, len);
         }
@@ -97,9 +106,29 @@ public class SystemOutputInterceptor extends FilterOutputStream {
      * Intercepts output - single characters
      */
     public void write(int b) throws IOException {
-        Boolean result = (Boolean) callback.call(String.valueOf((char) b));
+        Boolean result = (Boolean) callback.call(consoleId.get().intValue(), String.valueOf((char)
b));
         if (result) {
             out.write(b);
         }
     }
+
+    /**
+     * Threads executing a script should call this method at the start of execution
+     * in order to set the id of the console that is hosting the thread of execution.  This
+     * should be called prior to any output that is generated.  The consoleId will
+     * be passed to the callback.
+     *
+     * @param consoleId id of the Console instance executing the script
+     */
+    public void setConsoleId(int consoleId) {
+        this.consoleId.set(Integer.valueOf(consoleId));
+    }
+
+    /**
+     * Threads executing a script should call this method after
+     * execution completes in order to unregister the consoleId.
+     */
+    public void removeConsoleId() {
+        this.consoleId.remove();
+    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-groovy/blob/bfb135e6/subprojects/groovy-console/src/test/groovy/groovy/swing/SwingBuilderConsoleTest.groovy
----------------------------------------------------------------------
diff --git a/subprojects/groovy-console/src/test/groovy/groovy/swing/SwingBuilderConsoleTest.groovy
b/subprojects/groovy-console/src/test/groovy/groovy/swing/SwingBuilderConsoleTest.groovy
index 9ef89c2..06f94f8 100644
--- a/subprojects/groovy-console/src/test/groovy/groovy/swing/SwingBuilderConsoleTest.groovy
+++ b/subprojects/groovy-console/src/test/groovy/groovy/swing/SwingBuilderConsoleTest.groovy
@@ -435,4 +435,58 @@ class SwingBuilderConsoleTest extends GroovySwingTestCase {
             }
         }
     }
+
+    void testSystemOutputAndErrorRedirectedToCorrectConsole() {
+        testInEDT {
+            SwingUtilities.metaClass.static.invokeLater = { Runnable runnable ->
+                runnable.run()
+            }
+            Thread.metaClass.static.start = { Runnable runnable ->
+                runnable.run()
+            }
+
+            Console.prefs = testPreferences
+
+            try {
+                def swing = new SwingBuilder()
+                final Console console = new Console()
+                swing.controller = console
+                swing.build(new ConsoleActions())
+                console.run()
+                console.fileNewWindow()
+                final Console console2 = Console.consoleControllers.last()
+
+                console.showScriptInOutput = false
+                console2.showScriptInOutput = false
+
+                def doc = console.outputArea.document
+                def doc2 = console2.outputArea.document
+
+                assert console.consoleId != console2.consoleId
+
+                console.inputArea.text = 'println "test1"'
+                console.runScript()
+
+                assert 'test1' == doc.getText(0, doc.length).trim()
+                assert '' == doc2.getText(0, doc2.length).trim()
+
+                console2.inputArea.text = 'println "test2"'
+                console2.runScript()
+
+                assert 'test1' == doc.getText(0, doc.length).trim()
+                assert 'test2' == doc2.getText(0, doc2.length).trim()
+
+                console2.inputArea.text = 'System.err.println "error2"'
+                console2.runScript()
+
+                assert 'test1' == doc.getText(0, doc.length).trim()
+                assert doc2.getText(0, doc2.length) ==~ /(?s)(test2)[^\w].*(error2).*/
+            } finally {
+                GroovySystem.metaClassRegistry.removeMetaClass(Thread)
+                GroovySystem.metaClassRegistry.removeMetaClass(SwingUtilities)
+                GroovySystem.metaClassRegistry.removeMetaClass(Preferences)
+            }
+        }
+    }
+
 }


Mime
View raw message