views:

146

answers:

3

Is there some way I can catch when a method generates a write to STDERR? I'm trying to pre-pend some information with each STDERR write.

let's say our method is:

parser.thatGeneratesSTDERR();

it'll generate something like

line 37:29 no viable alternative at character 'a'

can I just wrap it with something that catches the stderr to be written and pre-pend some info so it'll look like this instead:

File: mybadfile.txt -- line 37:29 no viable alternative at character 'a'

I know I could probably dig through the actual code that does the STDERR writing but I really don't want to do that -- I'd rather just wrap some code around this method instead.

I should note that this method doesn't always generate STDERR -- the reason I'm trying to catch them is that it SHOULDN'T be generating any STDERR -- but since this is called on quite a few files (over 40) I never know which file is generating the error message -- it takes forever to find.

UPDATE so yeh, we can change our STDERR -- I was just forgetting that I need to override my println in my new STDERR... here's the relevant code:

public static String errfile = "";

static {
  final PrintStream currentErr = System.err;
  PrintStream newErr = new PrintStream(currentErr)
  { 
    public void println(String string) {
      print("File: " + errfile + " --");
      print(string);
      super.println();
    }
  };

  System.setErr(newErr);
}

then for each file that I'm testing all I have to do is change errfile to the filename and my output comes out expected...

thanks a lot!

+1  A: 

Sounds like you probably want to look at Aspect Oriented Programming (AOP). Using AOP, you can create a proxy to the parser you are calling. Before the method call thatGeneratesSTDERR() you can have it invoke you call. From your call you can output the information you want.

Note that it might take a bit of reading to understand how AOP works.

AspectJ - http://www.eclipse.org/aspectj/

AOP Alliance - http://sourceforge.net/projects/aopalliance

Chris Dail
A: 

You can use System.setErr to redirect stderr to your own PrintStream.

jdigital
+1  A: 

I'm not sure if this will work, given how System.setErr works.

I would create a new class that extends print stream and overwrites the methods to prepend your comment. Then set the error stream to your new printstream. Do not call System.err.printxxx from this new class.

ex...

class PrependPrintStream extends PrintStream {

PrependPrintStream(PrintStream ps, String pre){...}
...
public void print(boolean b) {
super.print(this.pre);
super.print(b);
}
...

I looked into sun's PrintStream impl, and it looks like all printxxx delegate to write(String) which is private instead of protected. I guess you can copy/paste the code.

EDIT::

A much better solution is to use Logging instead of System.err. This allows you to turn off and on your statements and allows you to create a custom error handler. Your specific handler could prepend the statement you wish to the string before printing to System.err. This also has the advantage that only statements that use your specific logger would have the prepended text and other calls to System.err wouldn't.

KitsuneYMG
yeh.. unfortunately I am nowhere even considering delving into the code that logs to stderr .. I just want it overridden and it works now -- thnx
feydr