001 /** 002 * Copyright (C) 2009, Progress Software Corporation and/or its 003 * subsidiaries or affiliates. All rights reserved. 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.fusesource.jansi; 019 020 import static org.fusesource.jansi.internal.CLibrary.STDOUT_FILENO; 021 import static org.fusesource.jansi.internal.CLibrary.isatty; 022 023 import java.io.FilterOutputStream; 024 import java.io.IOException; 025 import java.io.OutputStream; 026 import java.io.PrintStream; 027 028 /** 029 * Provides consistent access to an ANSI aware console PrintStream. 030 * 031 * @author <a href="http://hiramchirino.com">Hiram Chirino</a> 032 * @since 1.0 033 */ 034 public class AnsiConsole { 035 036 public static final PrintStream system_out = System.out; 037 public static final PrintStream out = new PrintStream(wrapOutputStream(system_out)); 038 039 public static final PrintStream system_err = System.err; 040 public static final PrintStream err = new PrintStream(wrapOutputStream(system_err)); 041 042 private static int installed; 043 044 public static OutputStream wrapOutputStream(final OutputStream stream) { 045 String os = System.getProperty("os.name"); 046 if( os.startsWith("Windows") ) { 047 048 // On windows we know the console does not interpret ANSI codes.. 049 try { 050 return new WindowsAnsiOutputStream(stream); 051 } catch (Throwable ignore) { 052 // this happens when JNA is not in the path.. or 053 // this happens when the stdout is being redirected to a file. 054 } 055 056 // Use the ANSIOutputStream to strip out the ANSI escape sequences. 057 return new AnsiOutputStream(stream); 058 } 059 060 // We must be on some unix variant.. 061 try { 062 // If we can detect that stdout is not a tty.. then setup 063 // to strip the ANSI sequences.. 064 int rc = isatty(STDOUT_FILENO); 065 if( rc==0 ) { 066 return new AnsiOutputStream(stream); 067 } 068 069 // These erros happen if the JNI lib is not available for your platform. 070 } catch (NoClassDefFoundError ignore) { 071 } catch (UnsatisfiedLinkError ignore) { 072 } 073 074 // By default we assume your Unix tty can handle ANSI codes. 075 // Just wrap it up so that when we get closed, we reset the 076 // attributes. 077 return new FilterOutputStream(stream) { 078 @Override 079 public void close() throws IOException { 080 write(AnsiOutputStream.REST_CODE); 081 flush(); 082 super.close(); 083 } 084 }; 085 } 086 087 /** 088 * If the standard out natively supports ANSI escape codes, then this just 089 * returns System.out, otherwise it will provide an ANSI aware PrintStream 090 * which strips out the ANSI escape sequences or which implement the escape 091 * sequences. 092 * 093 * @return a PrintStream which is ANSI aware. 094 */ 095 public static PrintStream out() { 096 return out; 097 } 098 099 /** 100 * If the standard out natively supports ANSI escape codes, then this just 101 * returns System.err, otherwise it will provide an ANSI aware PrintStream 102 * which strips out the ANSI escape sequences or which implement the escape 103 * sequences. 104 * 105 * @return a PrintStream which is ANSI aware. 106 */ 107 public static PrintStream err() { 108 return err; 109 } 110 111 /** 112 * Install Console.out to System.out. 113 */ 114 synchronized static public void systemInstall() { 115 installed++; 116 if( installed==1 ) { 117 System.setOut(out); 118 System.setErr(err); 119 } 120 } 121 122 /** 123 * undo a previous {@link #systemInstall()}. If {@link #systemInstall()} was called 124 * multiple times, it {@link #systemUninstall()} must call the same number of times before 125 * it is actually uninstalled. 126 */ 127 synchronized public static void systemUninstall() { 128 installed--; 129 if( installed==0 ) { 130 System.setOut(system_out); 131 System.setErr(system_err); 132 } 133 } 134 135 }