I have some legacy code (or rather some code we don’t control but we have to use) that writes a lot of statements to system.out/err.
At the same time, we are using a framework that uses a custom logging system wrapped around log4j (again, unfortunately we don’t control this).
So I’m trying to redirect the out and err stream to a custom PrintStream that will use the logging system. I was reading about the System.setLog() and System.setErr() methods but the problem is that I would need to write my own PrintStream class that wraps around the logging system in use. That would be a huge headache.
Is there a simple way to achieve this?
Just to add to Rick’s and Mikhail’s solutions, which are really the only option in this scenario, I wanted to give an example of how creating a custom OutputStream can potentially lead to not so easy to detect/fix problems. Here’s some code:
This example shows the pitfalls of using a custom output stream. For simplicity the write() function uses a log4j logger, but this can be replaced with any custom logging facility (such as the one in my scenario). The main function creates a PrintStream that wraps a CustomOutputStream and set the output stream to point to it. Then it executes a System.out.println() statement. This statement is redirected to the CustomOutputStream which redirects it to a logger. Unfortunately, since the logger is lazy initialized, it will acquire a copy of the console output stream (as per the log4j configuration file which defines a ConsoleAppender) too late, i.e., the output stream will point to the CustomOutputStream we just created causing a redirection loop and thus a StackOverflowError at runtime.
Now, with log4j this is easy to fix: we just need to initialize the log4j framework before we call System.setOut(), e.g., by uncommenting the first line of the main function. Luckily for me, the custom logging facility I have to deal with is just a wrapper around log4j and I know it will get initialized before it’s too late. However, in the case of a totally custom logging facility that uses System.out/err under the cover, unless the source code is accessible, it’s impossible to tell if and where direct calls to System.out/err are performed instead of calls to a PrintStream reference acquired during initialization. The only work around I can think of for this particular case would be to retrieve the function call stack and detect redirection loops, since the write() functions should not be recursive.