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 }