/*
* Copyright 2014 TWO SIGMA OPEN SOURCE, LLC
*
* Licensed 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 com.twosigma.beaker.jvm.threads;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Map;
public class BeakerStdOutErrHandler {
private static BeakerStdOutErrHandler instance;
static synchronized public void init() {
if (instance == null) {
instance = new BeakerStdOutErrHandler();
instance.theinit();
}
}
static synchronized public void fini() {
if (instance != null) {
instance.thefini();
instance = null;
}
}
static synchronized public void setOutputHandler(BeakerOutputHandler out, BeakerOutputHandler err) {
if (instance != null)
instance.theSetOutputHandler(out, err);
}
static synchronized public void setDefaultOutputHandler(BeakerOutputHandler out, BeakerOutputHandler err) {
if (instance != null)
instance.theSetDefaultOutputHandler(out, err);
}
static synchronized public void clrOutputHandler() {
if (instance != null)
instance.theClrOutputHandler();
}
static synchronized public PrintStream out() {
if (instance != null && instance.orig_out!=null)
return instance.orig_out;
return System.out;
}
static synchronized public PrintStream err() {
if (instance != null && instance.orig_err!=null)
return instance.orig_err;
return System.err;
}
private PrintStream orig_out;
private PrintStream orig_err;
private class MyOutputStream extends OutputStream {
private boolean is_out;
public MyOutputStream(boolean isout) {
is_out = isout;
}
@Override
public void write(int b) throws IOException {
instance.write(is_out, b);
}
@Override
public void write(byte[] b) throws IOException {
instance.write(is_out, b);
}
@Override
public void write(byte[] b, int off, int len) throws IOException {
instance.write(is_out, b, off, len);
}
}
private void theinit() {
orig_out = System.out;
orig_err = System.err;
System.setOut(new PrintStream(new MyOutputStream(true)));
System.setErr(new PrintStream(new MyOutputStream(false)));
}
private void thefini() {
System.setOut(orig_out);
System.setErr(orig_err);
}
private class threadOutputHandler {
public BeakerOutputHandler out_handler;
public BeakerOutputHandler err_handler;
}
private Map<Long,threadOutputHandler> thrHandlers = new HashMap<Long,threadOutputHandler>();
private BeakerOutputHandler def_out;
private BeakerOutputHandler def_err;
private synchronized void theSetOutputHandler(BeakerOutputHandler out, BeakerOutputHandler err) {
long id = Thread.currentThread().getId();
threadOutputHandler t;
if (!thrHandlers.containsKey(id)) {
t = new threadOutputHandler();
thrHandlers.put(id, t);
} else {
t = thrHandlers.get(id);
}
t.out_handler = out;
t.err_handler = err;
}
private synchronized void theSetDefaultOutputHandler(BeakerOutputHandler out, BeakerOutputHandler err) {
def_out = out;
def_err = err;
}
private synchronized void theClrOutputHandler() {
long id = Thread.currentThread().getId();
thrHandlers.remove(id);
}
private BeakerOutputHandler getHandler(boolean out) {
long id = Thread.currentThread().getId();
if (thrHandlers.containsKey(id)) {
threadOutputHandler t = thrHandlers.get(id);
if (out)
return t.out_handler;
return t.err_handler;
} else if (def_out!=null || def_err!=null) {
// WARNING: memory leak - we never clean up these if the thread exit
threadOutputHandler t = new threadOutputHandler();
t.out_handler = def_out;
t.err_handler = def_err;
thrHandlers.put(id, t);
}
if(out)
return def_out;
return def_err;
}
private synchronized void write(boolean isout, int b) throws IOException {
BeakerOutputHandler hdl = getHandler(isout);
if (hdl!=null) hdl.write(b);
else if(isout)
orig_out.write(b);
else
orig_err.write(b);
}
private synchronized void write(boolean isout, byte[] b) throws IOException {
BeakerOutputHandler hdl = getHandler(isout);
if (hdl!=null) hdl.write(b);
else if(isout)
orig_out.write(b);
else
orig_err.write(b);
}
private synchronized void write(boolean isout, byte[] b, int off, int len) throws IOException {
BeakerOutputHandler hdl = getHandler(isout);
if (hdl!=null) hdl.write(b, off, len);
else if(isout)
orig_out.write(b);
else
orig_err.write(b);
}
}