geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jdil...@apache.org
Subject svn commit: r641723 - in /geronimo/gshell/trunk/gshell-support/gshell-common/src: main/java/org/apache/geronimo/gshell/common/ test/java/org/apache/geronimo/gshell/common/
Date Thu, 27 Mar 2008 07:17:17 GMT
Author: jdillon
Date: Thu Mar 27 00:17:16 2008
New Revision: 641723

URL: http://svn.apache.org/viewvc?rev=641723&view=rev
Log:
(GSHELL-89) Bring over the system hijacking code from the groovy-maven-plugin stuff, tidy
up for Java 5

Added:
    geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/StreamPair.java
  (with props)
    geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/SystemOutputHijacker.java
  (with props)
    geronimo/gshell/trunk/gshell-support/gshell-common/src/test/java/org/apache/geronimo/gshell/common/SystemOutputHijackerTest.java
  (with props)

Added: geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/StreamPair.java
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/StreamPair.java?rev=641723&view=auto
==============================================================================
--- geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/StreamPair.java
(added)
+++ geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/StreamPair.java
Thu Mar 27 00:17:16 2008
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.gshell.common;
+
+import org.apache.geronimo.gshell.common.tostring.ReflectionToStringBuilder;
+import org.apache.geronimo.gshell.common.tostring.ToStringStyle;
+
+import java.io.PrintStream;
+
+/**
+ * Contains a pair of {@link PrintStream} objects.
+ *
+ * @version $Rev$ $Date$
+ */
+public class StreamPair
+{
+    public final PrintStream out;
+    
+    public final PrintStream err;
+    
+    public final boolean combined;
+    
+    public StreamPair(final PrintStream out, final PrintStream err) {
+        assert out != null;
+        assert err != null;
+        
+        this.out = out;
+        this.err = err;
+        this.combined = (out == err);
+    }
+    
+    public StreamPair(final PrintStream out) {
+        assert out != null;
+        
+        this.out = out;
+        this.err = out;
+        this.combined = true;
+    }
+    
+    public PrintStream get(final Type type) {
+        assert type != null;
+
+        return type.get(this);
+    }
+
+    public String toString() {
+        return ReflectionToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
+    }
+
+    public void flush() {
+        out.flush();
+        
+        if (!combined) {
+            err.flush();
+        }
+    }
+    
+    public void close() {
+        out.close();
+        
+        if (!combined) {
+            err.close();
+        }
+    }
+
+    /**
+     * Create a new pair as System is currently configured.
+     */
+    public static StreamPair system() {
+        return new StreamPair(System.out, System.err);
+    }
+
+    /**
+     * Install the given stream pair as the System streams.
+     */
+    public static void system(final StreamPair streams) {
+        assert streams != null;
+
+        System.setOut(streams.out);
+        System.setErr(streams.err);
+    }
+
+    /**
+     * The original System streams (as they were when this class loads).
+     */
+    public static final StreamPair SYSTEM = system();
+
+    /**
+     * Stream type.
+     */
+    public static enum Type
+    {
+        OUT, ERR;
+
+        private PrintStream get(final StreamPair pair) {
+            assert pair != null;
+
+            switch (this) {
+                case OUT:
+                    return pair.out;
+
+                case ERR:
+                    return pair.err;
+            }
+
+            // Should never happen
+            throw new InternalError();
+        }
+    }
+}

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/StreamPair.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/StreamPair.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/StreamPair.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/SystemOutputHijacker.java
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/SystemOutputHijacker.java?rev=641723&view=auto
==============================================================================
--- geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/SystemOutputHijacker.java
(added)
+++ geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/SystemOutputHijacker.java
Thu Mar 27 00:17:16 2008
@@ -0,0 +1,268 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.gshell.common;
+
+import java.io.PrintStream;
+import java.io.IOException;
+import java.io.ByteArrayOutputStream;
+
+/**
+ * Hijacks the systems standard output and error streams on a per-thread basis
+ * and redirects to given streams.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SystemOutputHijacker
+{
+    /**
+     * Contains a {@link StreamRegistration} for the current thread if its registered, else
null.
+     */
+    private static final InheritableThreadLocal<StreamRegistration> registrations =
new InheritableThreadLocal<StreamRegistration>();
+    
+    /**
+     * The previously installed System streams, initialized when installing.
+     */
+    private static StreamPair previous;
+    
+    /**
+     * Flag to indicate if the hijacker is installed or not.
+     */
+    private static boolean installed;
+
+    /**
+     * Check if the hijacker has been installed.
+     */
+    public static synchronized boolean isInstalled() {
+        return installed;
+    }
+    
+    private static synchronized void ensureInstalled() {
+        if (!isInstalled()) {
+            throw new IllegalStateException("Not installed");
+        }
+    }
+    
+    /**
+     * Install the hijacker.
+     */
+    public static synchronized void install() {
+        if (installed) {
+            throw new IllegalStateException("Already installed");
+        }
+        
+        // Capture the current set of streams
+        previous = new StreamPair(System.out, System.err);
+        
+        // Install our streams
+        System.setOut(new DelegateStream(StreamPair.Type.OUT));
+        System.setErr(new DelegateStream(StreamPair.Type.ERR));
+        
+        installed = true;
+    }
+    
+    /**
+     * Install the hijacker and register streams for the current thread.
+     */
+    public static synchronized void install(final PrintStream out, final PrintStream err)
{
+        install();
+        register(out, err);
+    }
+    
+    /**
+     * Install the hijacker and register combinded streams for the current thread.
+     */
+    public static synchronized void install(final PrintStream out) {
+        install();
+        register(out);
+    }
+    
+    /**
+     * Uninstall the hijacker.
+     */
+    public static synchronized void uninstall() {
+        ensureInstalled();
+        
+        System.setOut(previous.out);
+        System.setErr(previous.err);
+        
+        previous = null;
+        installed = false;
+    }
+    
+    /**
+     * Get the current stream registration.
+     */
+    private static synchronized StreamRegistration registration(final boolean required) {
+        if (required) {
+            ensureRegistered();
+        }
+        
+        return registrations.get();
+    }
+    
+    /**
+     * Check if there are streams registered for the current thread.
+     */
+    public static synchronized boolean isRegistered() {
+        return registration(false) != null;
+    }
+    
+    private static synchronized void ensureRegistered() {
+        ensureInstalled();
+        
+        if (!isRegistered()) {
+            throw new IllegalStateException("Streams not registered for thread: " + Thread.currentThread());
+        }
+    }
+    
+    /**
+     * Register streams for the current thread.
+     */
+    public static synchronized void register(final PrintStream out, final PrintStream err)
{
+        ensureInstalled();
+        
+        StreamRegistration prev = registration(false);
+        
+        StreamPair pair = new StreamPair(out, err);
+        
+        StreamRegistration next = new StreamRegistration(pair, prev);
+        
+        registrations.set(next);
+    }
+    
+    /**
+     * Register combinded streams for the current thread.
+     */
+    public static synchronized void register(final PrintStream out) {
+        register(out, out);
+    }
+    
+    /**
+     * Register streams for the current thread.
+     */
+    public static synchronized void register(final StreamPair pair) {
+        assert pair != null;
+        
+        register(pair.out, pair.err);
+    }
+    
+    /**
+     * Reregister streams for the current thread, and restore the previous if any.
+     */
+    public static synchronized void deregister() {
+        StreamRegistration cur = registration(true);
+        
+        registrations.set(cur.previous);
+    }
+    
+    /**
+     * Stream registration information.
+     */
+    private static class StreamRegistration
+    {
+        public final StreamPair streams;
+        
+        public final StreamRegistration previous;
+        
+        public StreamRegistration(final StreamPair streams, final StreamRegistration previous)
{
+            assert streams != null;
+            
+            this.streams = streams;
+            this.previous = previous;
+        }
+    }
+    
+    /**
+     * Returns the currently registered streams.
+     */
+    private static synchronized StreamPair current() {
+        StreamRegistration reg = registration(true);
+        
+        return reg.streams;
+    }
+    
+    /**
+     * Delegates write calls to the currently registered stream.
+     */
+    private static class DelegateStream
+        extends PrintStream
+    {
+        private static final ByteArrayOutputStream NULL_OUTPUT = new ByteArrayOutputStream();
+        
+        private final StreamPair.Type type;
+        
+        public DelegateStream(final StreamPair.Type type) {
+            super(NULL_OUTPUT);
+            
+            assert type != null;
+            
+            this.type = type;
+        }
+        
+        private PrintStream get() {
+            return current().get(type);
+        }
+        
+        public void write(final int b) {
+            get().write(b);
+        }
+        
+        public void write(final byte b[]) throws IOException {
+            get().write(b, 0, b.length);
+        }
+        
+        public void write(final byte[] b, final int off, final int len) {
+            get().write(b, off, len);
+        }
+        
+        public void flush() {
+            get().flush();
+        }
+
+        public void close() {
+            get().close();
+        }
+    }
+
+    //
+    // System Stream Restoration.  This stuff needs more testing, not sure its working as
I'd like... :-(
+    //
+
+    /**
+     * Restores the System streams to the given pair and resets the hijacker state to uninstalled.
+     */
+    public static synchronized void restore(final StreamPair streams) {
+        assert streams != null;
+
+        StreamPair.system(streams);
+
+        previous = null;
+        installed = false;
+    }
+
+    /**
+     * Restores the original System streams from {@link StreamPair#SYSTEM} and resets
+     * the hijacker state to uninstalled.
+     */
+    public static synchronized void restore() {
+        restore(StreamPair.SYSTEM);
+    }
+
+}

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/SystemOutputHijacker.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/SystemOutputHijacker.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/main/java/org/apache/geronimo/gshell/common/SystemOutputHijacker.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: geronimo/gshell/trunk/gshell-support/gshell-common/src/test/java/org/apache/geronimo/gshell/common/SystemOutputHijackerTest.java
URL: http://svn.apache.org/viewvc/geronimo/gshell/trunk/gshell-support/gshell-common/src/test/java/org/apache/geronimo/gshell/common/SystemOutputHijackerTest.java?rev=641723&view=auto
==============================================================================
--- geronimo/gshell/trunk/gshell-support/gshell-common/src/test/java/org/apache/geronimo/gshell/common/SystemOutputHijackerTest.java
(added)
+++ geronimo/gshell/trunk/gshell-support/gshell-common/src/test/java/org/apache/geronimo/gshell/common/SystemOutputHijackerTest.java
Thu Mar 27 00:17:16 2008
@@ -0,0 +1,209 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.geronimo.gshell.common;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+
+import junit.framework.TestCase;
+
+/**
+ * Tests for the {@link SystemOutputHijacker} class.
+ *
+ * @version $Rev$ $Date$
+ */
+public class SystemOutputHijackerTest
+    extends TestCase
+{
+    private ByteArrayOutputStream buff;
+
+    private PrintStream out;
+    
+    protected void setUp() throws Exception {
+        buff = new ByteArrayOutputStream();
+        out = new PrintStream(buff);
+
+        assertFalse(SystemOutputHijacker.isInstalled());
+    }
+
+    protected void tearDown() throws Exception {
+        buff = null;
+        out = null;
+
+        assertFalse(SystemOutputHijacker.isInstalled());
+    }
+
+    private void installOut() throws Exception {
+        assertFalse(SystemOutputHijacker.isRegistered());
+
+        SystemOutputHijacker.install(out);
+
+        assertTrue(SystemOutputHijacker.isInstalled());
+        assertTrue(SystemOutputHijacker.isRegistered());
+    }
+
+    private void deregisterAndUninstall() throws Exception {
+        SystemOutputHijacker.deregister();
+
+        assertFalse(SystemOutputHijacker.isRegistered());
+
+        SystemOutputHijacker.uninstall();
+
+        assertFalse(SystemOutputHijacker.isInstalled());
+    }
+
+    public void testInstallWithStream() throws Exception {
+        System.out.println("before");
+
+        installOut();
+        
+        try {
+            System.out.print("hijacked");
+        }
+        finally {
+            deregisterAndUninstall();
+        }
+        
+        System.out.println("after");
+        
+        String msg = new String(buff.toByteArray());
+        
+        assertEquals("hijacked", msg);
+    }
+    
+    public void testInstallRegisterWithStream() throws Exception {
+        System.out.println("before");
+        
+        SystemOutputHijacker.install();
+        assertTrue(SystemOutputHijacker.isInstalled());
+
+        assertFalse(SystemOutputHijacker.isRegistered());
+        SystemOutputHijacker.register(out);
+        assertTrue(SystemOutputHijacker.isRegistered());
+        
+        try {
+            System.out.print("hijacked");
+        }
+        finally {
+            deregisterAndUninstall();
+        }
+        
+        System.out.println("after");
+        
+        String msg = new String(buff.toByteArray());
+        
+        assertEquals("hijacked", msg);
+    }
+    
+    public void testDualStreams() throws Exception {
+        ByteArrayOutputStream errBuff = new ByteArrayOutputStream();
+        PrintStream err = new PrintStream(errBuff);
+        
+        System.out.println("before");
+        System.err.println("BEFORE");
+        
+        SystemOutputHijacker.install(out, err);
+        
+        assertTrue(SystemOutputHijacker.isInstalled());
+        assertTrue(SystemOutputHijacker.isRegistered());
+        
+        try {
+            System.out.print("hijacked");
+            System.err.print("HIJACKED");
+        }
+        finally {
+            deregisterAndUninstall();
+        }
+        
+        System.out.println("after");
+        System.err.println("AFTER");
+        
+        assertEquals("hijacked", new String(buff.toByteArray()));
+        assertEquals("HIJACKED", new String(errBuff.toByteArray()));
+    }
+    
+    public void testChildThreads() throws Exception {
+        System.out.println("before");
+        
+        installOut();
+        
+        Runnable task = new Runnable() {
+            public void run() {
+                System.out.print("hijacked");
+            }
+        };
+        
+        try {
+            System.out.print("<");
+            
+            Thread t = new Thread(task);
+            t.start();
+            t.join();
+            
+            System.out.print(">");
+        }
+        finally {
+            deregisterAndUninstall();
+        }
+        
+        System.out.println("after");
+        
+        String msg = new String(buff.toByteArray());
+        
+        assertEquals("<hijacked>", msg);
+    }
+    
+    public void testNestedRegistration() throws Exception {
+        System.out.println("before");
+
+        installOut();
+        
+        try {
+            System.out.print("hijacked");
+            
+            ByteArrayOutputStream childBuff = new ByteArrayOutputStream();
+            PrintStream childOut = new PrintStream(childBuff);
+            
+            System.out.print("!");
+            
+            SystemOutputHijacker.register(childOut);
+            
+            try {
+                System.out.print("child");
+            }
+            finally {
+                SystemOutputHijacker.deregister();
+            }
+
+            System.out.print("!");
+
+            assertEquals("child", new String(childBuff.toByteArray()));
+        }
+        finally {
+            deregisterAndUninstall();
+        }
+        
+        System.out.println("after");
+        
+        String msg = new String(buff.toByteArray());
+        
+        assertEquals("hijacked!!", msg);
+    }
+}

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/test/java/org/apache/geronimo/gshell/common/SystemOutputHijackerTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/test/java/org/apache/geronimo/gshell/common/SystemOutputHijackerTest.java
------------------------------------------------------------------------------
    svn:keywords = Date Author Id Revision HeadURL

Propchange: geronimo/gshell/trunk/gshell-support/gshell-common/src/test/java/org/apache/geronimo/gshell/common/SystemOutputHijackerTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message