/*******************************************************************************
* Copyright (c) 2001, 2010 Mathew A. Nelson and Robocode contributors
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://robocode.sourceforge.net/license/epl-v10.html
*
* Contributors:
* Mathew A. Nelson
* - Initial API and implementation
* Flemming N. Larsen
* - Optimized regarding thread synchronization
*******************************************************************************/
package net.sf.robocode.host.io;
import java.io.PrintWriter;
import java.io.StringWriter;
/**
* @author Mathew A. Nelson (original)
* @author Flemming N. Larsen (contributor)
*/
public class RobotOutputStream extends java.io.PrintStream {
private final static int MAX = 100;
private int count = 0;
private boolean messaged = false;
private final StringBuilder text;
private final Object syncRoot = new Object();
public RobotOutputStream() {
super(new BufferedPipedOutputStream(128, true));
this.text = new StringBuilder(8192);
}
public String readAndReset() {
synchronized (syncRoot) {
// Out's counter must be reset before processing event.
// Otherwise, it will not be reset when printing in the onScannedEvent()
// before a scan() call, which will potentially cause a new onScannedEvent()
// and therefore not be able to reset the counter.
count = 0;
if (text.length() > 0) {
final String result = text.toString();
text.setLength(0);
return result;
}
return "";
}
}
private boolean isOkToPrint() {
synchronized (syncRoot) {
if (count++ > MAX) {
if (!messaged) {
text.append("\n");
text.append(
"SYSTEM: This robot is printing too much between actions. Output stopped until next action.");
text.append("\n");
messaged = true;
}
return false;
}
messaged = false;
return true;
}
}
@Override
public void print(char[] s) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(s);
if (s != null) {
count += (s.length / 1000);
}
}
}
}
@Override
public void print(char c) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(c);
}
}
}
@Override
public void print(double d) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(d);
}
}
}
@Override
public void print(float f) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(f);
}
}
}
@Override
public void print(int i) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(i);
}
}
}
@Override
public void print(long l) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(l);
}
}
}
@Override
public void print(Object obj) {
synchronized (syncRoot) {
if (isOkToPrint()) {
if (obj != null) {
String s = obj.toString();
text.append(s);
count += (s.length() / 1000);
} else {
text.append((Object) null);
}
}
}
}
@Override
public void print(String s) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(s);
if (s != null) {
count += (s.length() / 1000);
}
}
}
}
@Override
public void print(boolean b) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append(b);
}
}
}
@Override
public void println() {
print('\n');
}
@Override
public void println(char[] x) {
print(x);
print('\n');
}
@Override
public void println(char x) {
print(x);
print('\n');
}
@Override
public void println(double x) {
print(x);
print('\n');
}
@Override
public void println(float x) {
print(x);
print('\n');
}
@Override
public void println(int x) {
print(x);
print('\n');
}
@Override
public void println(long x) {
print(x);
print('\n');
}
@Override
public void println(Object x) {
print(x);
print('\n');
}
@Override
public void println(String x) {
print(x);
print('\n');
}
@Override
public void println(boolean x) {
print(x);
print('\n');
}
@Override
public void write(byte[] buf) {
write(buf, 0, buf.length);
}
@Override
public void write(byte[] buf, int off, int len) {
synchronized (syncRoot) {
if (isOkToPrint()) {
if (buf != null) {
for (int i = 0; i < len; i++) {
text.append((char) buf[off + i]);
}
count += (buf.length / 1000);
}
}
}
}
@Override
public void write(int b) {
synchronized (syncRoot) {
if (isOkToPrint()) {
text.append((char) b);
}
}
}
public void printStackTrace(Throwable t) {
if (t != null) {
synchronized (syncRoot) {
if (isOkToPrint()) {
StringWriter sw = new StringWriter();
final PrintWriter writer = new PrintWriter(sw);
t.printStackTrace(writer);
writer.flush();
text.append(sw.toString());
}
}
}
}
}