 Licensed to the Apache Software Foundation (ASF) under one or more
 contributor license agreements.  See the NOTICE file distributed with
 this work for additional information regarding copyright ownership.
 The ASF licenses this file to You 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.


Copied from
http://www.mail-archive.com/log4j-user@jakarta.apache.org/msg00445.html

--------------------------------------------------------------------------------
RE: diverting System.stderr/stdout into log4j
--------------------------------------------------------------------------------

From: Michael Smith 
Subject: RE: diverting System.stderr/stdout into log4j 
Date: Tue, 13 Mar 2001 06:46:04 -0800 

--------------------------------------------------------------------------------

There is another way!

In LogLog, completely ignore System.err.  Instead, use the following to get
the standard error stream:

PrintStream err =
  new PrintStream(new FileOutputStream(FileDescriptor.err));

When you use System.setErr, it changes System.err, but not
FileDescriptor.err, which maintains a descriptor for the original error
stream.

michael

For a sample program to test this, see below:

import java.io.*;

public class Stderr {

  public static void main(String[] args) {

    // create a print stream to represent a redirect
    PrintStream nonStandardErr = 
      new PrintStream(new ByteArrayOutputStream());
    
    // Redirect standard out and standard err
    System.setOut(nonStandardErr);
    System.setErr(nonStandardErr);
    
    // attempt to print something
    System.err.println("You should *not* see this on the console!");
	
    // the stuff that would appear in LogLog
    PrintStream logLogOut = 
      new PrintStream(new FileOutputStream(FileDescriptor.err));
    
    // attempt to print something
    logLogOut.println("You *should* see this on the console!");
  }
}



> -----Original Message-----
> From: Ceki Gülcü [mailto:cgu@qos.ch]
> Sent: Monday, March 12, 2001 7:18 PM
> To: LOG4J Users Mailing List
> Subject: RE: diverting System.stderr/stdout into log4j
>
>
>
> Hate to follow up on myself, but the System.setErr method
> reassigns the System.err variable. This can be deduced without
> experimentation because the user calls the System.err variable
> directly to print to the console, whatever it might be. Thus, the
> reference itself must change to allow the System.err variable to
> point to the new target stream.
>
> The funny part is that the err variable is declared 'public
> final' in the JDK source code. The setErr method makes a call to
> setErr0 which is declared as being 'native'. It looks like the
> native part is circumventing the JDK restrictions. I find this
> quite entertaining. Ceki
>
> At 00:58 13.03.2001 +0100, Ceki Gülcü wrote:
>
> >Running the risk of disappointing you here, although not full of
> bugs, log4j is not bug-free as bugs creep out regularly. They
> just get corrected quickly before many people are affected by them.
> >
> >The PrintStream se = System.err; LogLog.setPrintStream(see);
> combination is simple and rather bright. I initially overlooked
> the  PrintStream se = System.err; part, making me think that a
> lot of code needed to be modified to cater  for the redirected
> console case. The remedy looked worse than the illness. My fears
> are largely unfounded and the solution should work quite well if
> one is careful.
> >
> >Regards, Ceki
> >
> >ps: I wonder if System.err always refers to the real STDERR or
> if really gets reassigned with the setErr call. It's  easy to find out...
> >
> >At 23:20 12.03.2001 +0000, Joseph Panico wrote:
> >>Of course log4j is completely bug free, but that doesn't
> preclude user error. For instance, I neglected to add appenders
> in my config file (actually I intentionally left them out,
> thinking that would simply turn off logging) and then log4j went
> into an infinite loop. The setPrintStream makes sense to me.
> >>
> >>joe
> >>
> >>
> >>>From: Jim Moore <jim.moore@veritas.com>
> >>>Reply-To: "LOG4J Users Mailing List" <log4j-user@jakarta.apache.org>
> >>>To: 'LOG4J Users Mailing List' <log4j-user@jakarta.apache.org>
> >>>Subject: RE: diverting System.stderr/stdout into log4j
> >>>Date: Mon, 12 Mar 2001 18:10:37 -0500
> >>>
> >>>It doesn't.  I haven't worried about it, since log4j doesn't
> contain any
> >>>bugs and therefore it would never happen... :)
> >>>
> >>>Probably the best way to handle it is to add a
> >>>LogLog.setPrintStream(PrintStream) method, so you can do
> something like:
> >>>
> >>>// remember STDERR
> >>>PrintStream se = System.err;
> >>>
> >>>// make sure everything sent to System.err is logged
> >>>System.setErr(new PrintStream(new
> LoggingOutputStream(Category.getRoot(),
> >>>              Priority.WARN), true));
> >>>
> >>>// make sure everything sent to System.out is also logged
> >>>System.setOut(new PrintStream(new
> LoggingOutputStream(Category.getRoot(),
> >>>              Priority.INFO), true));
> >>>
> >>>// prevent infinate recursion in LogLog
> >>>LogLog.setPrintStream(se);
> >>>
> >>>
> >>>I can't think of any other way to do it in the current version besides
> >>>getting extremely kludgey by checking the stack to see if it's
> being called
> >>>from LogLog and logging out the the "real" STDERR then in the
> >>>LoggingOutputStream.  It can be done on the theory that LogLog
> wouldn't be
> >>>called very often, but still...
> >>>
> >>>-Jim Moore
> >>>
> >>>
> >>>-----Original Message-----
> >>>From: Ceki Gülcü [mailto:cgu@qos.ch]
> >>>Sent: Monday, March 12, 2001 5:15 PM
> >>>To: LOG4J Users Mailing List
> >>>Subject: RE: diverting System.stderr/stdout into log4j
> >>>
> >>>
> >>>Jim, Joseph,
> >>>
> >>>Here is a link containing Jim's code:
> >>>
> >>>http://marc.theaimsgroup.com/?l=log4j-user&m=98097669218571&w=2
> >>>
> >>>How does this code handle the infinite recursion problem mentioned by
> >>>Joseph? Ceki
> >>>
> >>>At 17:03 12.03.2001 -0500, Jim Moore wrote:
> >>>>Go to the mailing list archives (theAimsGroup.com is the
> best) and search
> >>>>for the thread with the subject of "Capturing System.err"
> >>>>
> >>>>-Jim Moore
> >>>>"I think so, Brain; but if we gave peas a chance, won't the
> lima beans get
> >>>>jealous?" - Pinky
> >>>>
> >>>>
> >>>>-----Original Message-----
> >>>>From: Joseph Panico [mailto:joe_panico@hotmail.com]
> >>>>Sent: Monday, March 12, 2001 4:43 PM
> >>>>To: log4j-user@jakarta.apache.org
> >>>>Subject: diverting System.stderr/stdout into log4j
> >>>>
> >>>>
> >>>>Folks,
> >>>>
> >>>>We use a number of third-party packages that do
> stderr.print... at various
> >>>>random places in their code. I'm finding it quite useful to
> divert these
> >>>>messages into our log4j heirarchy. I do this by replacing
> stderr/stdout
> >>>with
> >>>>
> >>>>my own PrintStreams that log the lines to a special log4j
> Category-- as
> >>>>suggested on this list a while back. The only
> fly-in-the-ointment with this
> >>>
> >>>>scheme is LogLog. If there is a problem with log4j such that
> it cannot log
> >>>>for some reason, then log4j internals use LogLog to attempt
> to print an
> >>>>error message. This obviously leads to an infinite recursion.
> Has anyone
> >>>>else been bothered by this? Would it make sense to add
> interface to LogLog
> >>>>which would set the PrintStream it uses to log its error messages to?
> >>>>
> >>>>thanks for any ideas
> >>>>
> >>>>joe


