/* * Scriptographer * * This file is part of Scriptographer, a Scripting Plugin for Adobe Illustrator * http://scriptographer.org/ * * Copyright (c) 2002-2010, Juerg Lehni * http://scratchdisk.com/ * * All rights reserved. See LICENSE file for details. * * File created on 07.12.2004. */ package com.scriptographer; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; import java.io.PrintStream; /** * @author lehni */ public class ConsoleOutputStream extends OutputStream { /** * the singleton object */ private static ConsoleOutputStream console = new ConsoleOutputStream(); /** * some constants */ private static final String lineSeparator = System.getProperty("line.separator"); private static final char newLine = lineSeparator.charAt(lineSeparator.length() - 1); private boolean enabled; // Use a ByteArrayOutputStream instead of a StringBuffer, // since we receive print(int) with bytes in the platform // encoding, not chars. private ByteArrayOutputStream buffer; private PrintStream stream; private PrintStream stdOut; private PrintStream stdErr; private ScriptographerCallback callback = null; private ConsoleOutputStream() { buffer = new ByteArrayOutputStream(); stream = new PrintStream(this); stdOut = System.out; stdErr = System.err; enabled = false; } private boolean receivedHeadlessError = false; /** * Adds chars to the internal StringBuffer until a new line char is * detected, in which case the collected line is written to the native * console window through writeLine. * * @see java.io.OutputStream#write(int) */ public void write(int b) throws IOException { // Detect the end of a received headless error. The only way to tell is // once we're receiving a new text from the main thread again. if (receivedHeadlessError && ScriptographerEngine.isMainThreadActive()) { ScriptographerEngine.logError(buffer.toString()); buffer.reset(); receivedHeadlessError = false; } char c = (char) b; if (c != 0) // Do not write out 0 chars, since they mess up the client side buffer.write(c); if (c == newLine) { // Only print to the console if we're in the right thread to prevent UI crashes. if (ScriptographerEngine.isMainThreadActive()) { if (enabled) { String str = buffer.toString(); buffer.reset(); // If there already is a newline at the end of this line, // remove it as callback.println adds it again... int pos = str.lastIndexOf(lineSeparator); if (pos > 0 && pos == str.length() - lineSeparator.length()) str = str.substring(0, pos); // Make sure we have the right line separators: str = str.replaceAll("\\n|\\r\\n|\\r", lineSeparator); // And convert tabs to 4 spaces str = str.replaceAll("\\t", " "); ScriptographerEngine.logConsole(str); callback.println(str); } } else if (ScriptographerEngine.isMacintosh() && !receivedHeadlessError) { // Filter out weird java.lang.ClassCastException: sun.java2d.HeadlessGraphicsEnvironment on OSX 10.5 receivedHeadlessError = buffer.toString().indexOf( "java.lang.ClassCastException: sun.java2d.HeadlessGraphicsEnvironment") != -1; } } } public static void enableOutput(boolean enabled) { console.enabled = enabled && console.callback != null; if (console.enabled && console.buffer.size() > 0) { try { // write a newline character so the buffer is flushed to the // console console.write(newLine); } catch (IOException e) { // never happens! } } } public static void enableRedirection(boolean enable) { if (enable) { System.setOut(console.stream); System.setErr(console.stream); } else { System.setOut(console.stdOut); System.setErr(console.stdErr); } } protected static void setCallback(ScriptographerCallback callback) { console.callback = callback; enableOutput(callback != null); } }