package edu.pdx.cs410J.grader;
import java.io.*;
/**
* This class represents a report that is generated as a result of
* running a student's program.
*
* @author David Whitlock
*/
public class Report {
/** The original <code>System.err</code> */
PrintStream consoleErr = System.err;
/** The original <code>System.out</code> */
PrintStream consoleOut = System.out;
/** The number of character columns in the log file. */
private static final int WIDTH = 72;
/** Write output of tests and other stuff to here. */
private PrintWriter log;
/** Are we finished? */
private boolean done = false;
private PrintStream ps;
/**
* Creates a new <code>Report</code> that sends its output to a
* given <code>PrintWriter</code>. This is useful when you want to
* dump to the console. The "student's" id is
* <code>"writer"</code>.
*/
public Report(PrintWriter pw) {
this.log = pw;
}
/**
* Creates a new <code>Report</code> for a given student. It will
* create a log file in given directory.
*
* @param id
* The student's login id
* @param logDir
* Directory into which the log file is placed.
*/
public Report(final String id, File logDir) {
if (!logDir.isDirectory()) {
throw new IllegalArgumentException(logDir +
" is not a directory");
}
if (!logDir.exists()) {
logDir.mkdirs();
}
String logFileName = id + ".log";
File logFile = new File(logDir, logFileName);
// Create a PrintStream around the log file. Set System.out and
// System.err to refer to this guy.
FileOutputStream fos = null;
try {
fos = new FileOutputStream(logFile);
} catch (IOException ex) {
throw new IllegalArgumentException("Could not open " +
logFileName);
}
/**
* Inner class used to prevent file stream from being closed until
* I say so. Other code may attempt to close System.out which
* result in this file stream being closed.
*/
class CheckedPrintStream extends PrintStream {
public CheckedPrintStream(OutputStream stream) {
super(stream);
}
public void close() {
if(Report.this.done) {
// Report.this.consoleOut.println("Report " + id +
// " is closing stream");
super.close();
}
// Report.this.consoleOut.println("Report " + id +
// " is not done yet");
}
}
// this.ps = System.out;
this.ps = new CheckedPrintStream(fos);
System.setOut(ps);
System.setErr(ps);
// Create a PrintWriter around the PrintStream
this.log = new PrintWriter(ps, true);
}
/**
* Makes note of an exception
*/
public void logException(String msg, Exception ex) {
println("** EXCEPTION " + msg);
ex.printStackTrace(this.log);
}
/**
* Flushes the stream that is being written to
*/
public void flush() {
this.log.flush();
}
/**
* Prints a left justified line of text to the log file.
*/
public void println(Object o) {
this.log.println(o);
}
/**
* Prints a left justified line of text to the log file.
*/
public void println(String text) {
this.log.println(text);
}
/**
* Prints a line of text to the log file and centers it.
*/
public void printlnCentered(String text) {
printBanner(text, ' ');
}
/**
* Prints a line of text to the log file, centers it, around
* surrounds it with a given character.
*/
public void printBanner(String text, char c) {
int length = text.length();
// Don't bother centering if the text is wider than the log.
if (length < WIDTH) {
int indent = (WIDTH - length) / 2;
for (int i = 0; i < indent - 1; i++) {
this.log.print(c);
}
this.log.print(' ');
this.log.flush();
}
this.log.print(text);
if (length < WIDTH) {
int indent = (WIDTH - length) / 2;
this.log.print(' ');
for (int i = 0; i < indent - 1; i++) {
this.log.print(c);
}
this.log.flush();
}
this.log.println("");
}
/**
* Signifies that this <code>Report</code> is done
*/
void done() {
this.done = true;
}
/**
* Make sure we're done when this <code>Report</code> gets garbage
* collected. This way, the stream will always get closed.
*/
public void finalize() {
this.done = true;
}
}