001/******************************************************************************* 002 * This software is provided as a supplement to the authors' textbooks on digital 003 * image processing published by Springer-Verlag in various languages and editions. 004 * Permission to use and distribute this software is granted under the BSD 2-Clause 005 * "Simplified" License (see http://opensource.org/licenses/BSD-2-Clause). 006 * Copyright (c) 2006-2016 Wilhelm Burger, Mark J. Burge. All rights reserved. 007 * Visit http://imagingbook.com for additional details. 008 *******************************************************************************/ 009 010package imagingbook.lib.ij; 011 012import ij.IJ; 013import imagingbook.lib.ij.IjLogStream; 014import imagingbook.lib.ij.IjLogStream; 015import imagingbook.lib.ij.IjLogStream; 016 017import java.io.ByteArrayOutputStream; 018import java.io.PrintStream; 019 020/** 021 * This class provides the functionality to divert output sent to the System.out 022 * and System.err streams to ImageJ's log console. The purpose is to allow 023 * use of existing Java classes or writing new generic Java classes that only 024 * output to System.out and are thus less dependent on ImageJ. 025 * 026 * @author W. Burger 027 * @version 2015-05-04 028 */ 029public class IjLogStream extends PrintStream { 030 031 private static PrintStream orgSystemOut = null; 032 private static PrintStream orgSystemErr = null; 033 private static PrintStream tmpSystemOut = null; 034 private static PrintStream tmpSystemErr = null; 035 036 /** 037 * Redirects all output sent to <code>System.out</code> and <code>System.err</code> 038 * to ImageJ's log console using empty prefix strings. 039 * Alternatively use 040 * {@link #redirectSystemOut(String)} and {@link #redirectSystemErr(String)} 041 * to redirect the streams separately and to specify individual prefix strings. 042 */ 043 public static void redirectSystem() { 044 redirectSystem("", ""); 045 } 046 047 /** 048 * Redirects all output sent to <code>System.out</code> and <code>System.err</code> 049 * to ImageJ's log console using the default prefixes. 050 * @param outPrefix The prefix string inserted at the start of each line sent to <code>System.out</code>. 051 * @param errPrefix The prefix string inserted at the start of each line sent to <code>System.err</code>. 052 */ 053 public static void redirectSystem(String outPrefix, String errPrefix) { 054 redirectSystemOut(outPrefix); 055 redirectSystemErr(errPrefix); 056 //IJ.log("[redirectSystem] streams created"); 057 } 058 059 /** 060 * Redirects all output sent to <code>System.out</code> to ImageJ's log console. 061 * @param prefix The prefix string inserted at the start of each output line. 062 * Pass <code>null</code> to use the default prefix or an empty string to 063 * remove the prefix. 064 */ 065 public static void redirectSystemOut(String prefix) { 066 if (orgSystemOut == null) { // has no effect if System.out is already replaced 067 orgSystemOut = System.out; // remember the original System.out stream 068 tmpSystemOut = new IjLogStream(prefix); 069 System.setOut(tmpSystemOut); 070 } 071 } 072 073 /** 074 * Redirects all output sent to <code>System.err</code> to ImageJ's log console. 075 * @param prefix The prefix string inserted at the start of each output line. 076 * Pass <code>null</code> to use the default prefix or an empty string to 077 * remove the prefix. 078 */ 079 public static void redirectSystemErr(String prefix) { 080 if (orgSystemErr == null) { // has no effect if System.out is already replaced 081 orgSystemErr = System.err; // remember the original System.out stream 082 tmpSystemErr = new IjLogStream(prefix); 083 System.setErr(tmpSystemErr); 084 } 085 } 086 087 /** 088 * Returns the redirection stream for {@code System.out} if it exists. 089 * Note that a reference to the current output stream can also be obtained directly from 090 * the {@code System.out} field. 091 * @return A reference to the {@code PrintStream} object currently substituting {@code System.out} 092 * or {@code null} of if {@code System.out} is currently not redirected. 093 */ 094 public static PrintStream getCurrentOutStream() { 095 return tmpSystemOut; 096 } 097 098 /** 099 * Returns the redirection stream for {@code System.err} if it exists. 100 * Note that a reference to the current output stream can also be obtained directly from 101 * the {@code System.err} field. 102 * @return A reference to the {@code PrintStream} object currently substituting {@code System.err} 103 * or {@code null} of if {@code System.err} is currently not redirected. 104 */ 105 public static PrintStream getCurrentErrStream() { 106 return tmpSystemErr; 107 } 108 109 /** 110 * Use this method to revert both <code>System.out</code> and <code>System.err</code> 111 * to their original output streams. 112 */ 113 public static void revertSystem() { 114 revertSystemOut(); 115 revertSystemErr(); 116 } 117 118 /** 119 * Use this method to revert<code>System.out</code> 120 * to the original output stream. 121 */ 122 public static void revertSystemOut() { 123 if (orgSystemOut != null && tmpSystemOut != null) { 124 tmpSystemOut.flush(); 125 tmpSystemOut.close(); 126 System.setOut(orgSystemOut); 127 orgSystemOut = null; 128 tmpSystemOut = null; 129 } 130 } 131 132 /** 133 * Use this method to revert<code>System.err</code> 134 * to the original output stream. 135 */ 136 public static void revertSystemErr() { 137 if (orgSystemErr != null && tmpSystemErr != null) { 138 tmpSystemErr.flush(); 139 tmpSystemErr.close(); 140 System.setErr(orgSystemErr); 141 orgSystemErr = null; 142 tmpSystemErr = null; 143 } 144 } 145 146 // ---------------------------------------------------------------- 147 148 private final String endOfLineSystem = System.getProperty("line.separator"); 149 private final String endOfLineShort = String.format("\n"); 150 private final ByteArrayOutputStream byteStream; 151 private final String prefix; 152 153 /** 154 * The only constructor, not to be used from outside (private). 155 * @param prefix The prefix string preceding every output line produced by this stream. 156 */ 157 private IjLogStream(String prefix) { 158 super(new ByteArrayOutputStream()); 159 this.byteStream = (ByteArrayOutputStream) this.out; 160 this.prefix = (prefix == null) ? "" : prefix; 161 } 162 163 @Override 164 // ever called? 165 public void write(byte[] b) { 166 this.write(b, 0, b.length); 167 } 168 169 @Override 170 public void write(byte[] b, int off, int len) { 171 String msg = new String(b, off, len); 172 if (msg.equals(endOfLineSystem) || msg.equals(endOfLineShort)) { // this is a newline sequence only 173 ejectBuffer(); 174 } 175 else { 176 byteStream.write(b, off, len); // append message to buffer 177 if (msg.endsWith(endOfLineSystem) || msg.endsWith(endOfLineShort)) { // line terminated by Newline 178 // note that this does not seem to happen ever (even with format)!? 179 ejectBuffer(); 180 } 181 } 182 } 183 184 @Override 185 // ever called? 186 public void write(int b) { 187 byteStream.write(b); 188 } 189 190 @Override 191 public void flush() { 192 if (byteStream.size() > 0) { 193 ejectBuffer(); 194 } 195 super.flush(); 196 } 197 198 @Override 199 public void close() { 200 super.close(); 201 } 202 203 private void ejectBuffer() { 204 IJ.log(prefix + byteStream.toString()); 205 byteStream.reset(); 206 } 207 208}