/*
* Copyright (C) 2007 the original author or authors.
*
* 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 org.codehaus.mojo.shitty.util;
import java.io.IOException;
import java.io.InterruptedIOException;
import java.io.OutputStream;
import java.io.PrintStream;
import groovy.lang.Closure;
/**
* Prefixes printed lines as instructed to by a given prefix rendering closure.
*
* @version $Id$
* @author <a href="mailto:jason@planet57.com">Jason Dillon</a>
*/
public class PrefixingStream
extends PrintStream
{
/**
* The callback closure which will return the prefix to be used.
*/
private Closure callback;
/**
* Flag to indicate if we are on a new line or not... start with a new line of course.
*/
private boolean newline = true;
public PrefixingStream(final Closure callback, final OutputStream out, final boolean autoFlush) {
super(out, autoFlush);
assert callback != null;
this.callback = callback;
}
public PrefixingStream(final Closure callback, final OutputStream out) {
this(callback, out, false);
}
public PrefixingStream(final String prefix, final OutputStream out, final boolean autoFlush) {
super(out, autoFlush);
this.callback = new Closure(this) {
public Object call(final Object[] args) {
return prefix;
}
};
}
public PrefixingStream(final String prefix, final OutputStream out) {
this(prefix, out, false);
}
public void write(final byte[] b, final int off, final int len) {
assert b != null;
assert off > -1;
assert len > -1;
//
// FIXME: This is super-ughly embedded '\n' handling crap, just kinda hacked my want into this...
// so it probabably sucks a lot :-P
//
/*
if (len > 1) {
for (int i=off; i<len; i++) {
if (b[i] == '\n') {
synchronized (this) {
// Write out the first bits before the new line
write(b, off, i - off);
// The write out the new line
write('\n');
newline = true;
// The write out everything else (recurses to find more embedded \n muck)
write(b, i + 1, len - i - off - 1);
// and then stop
return;
}
}
}
}
*/
synchronized (this) {
// if we are on a new line, then print the prefix
if (newline) {
Object result = callback.call(new String(b, off, len));
// Null result means don't write the prefix
if (result != null) {
byte[] prefix = String.valueOf(result).getBytes();
super.write(prefix, 0, prefix.length);
}
newline = false;
}
super.write(b, off, len);
}
// Check if there is a new line in the given string to reset the newline flag
for (int i=off; i<len; i++) {
if (b[i] == '\n') {
synchronized (this) {
newline = true;
}
break;
}
}
}
}