001package org.vishia.msgDispatch;
002
003import java.io.File;
004import java.util.TimeZone;
005
006import org.vishia.mainCmd.MainCmd;
007import org.vishia.mainCmd.MainCmd_ifc;
008import org.vishia.util.Assert;
009
010/**This class replaces the System.out and System.err with 2 inputs which creates
011 * a LogMessage and dispatch it with the Message Dispatcher.
012 * Without any other effort both outputs will be dispatch to the originally
013 * System.out and System.err output, but with additional time stamp and identification number.
014 * <br><br>
015 * The messages can be redirected and prevented using the {@link MsgDispatcher} capability.
016 * <br><br>
017 * @author Hartmut Schorrig
018 *
019 */
020public class MsgRedirectConsole extends MsgDispatcher
021{
022
023  /**Version, history and license.
024   * <ul>
025   * <li>2015-11-15 Hartmut new {@link MsgRedirectConsole#MsgRedirectConsole()} for simplest usage. 
026   * <li>2013-03-31 Hartmut new {@link #readConfig(File)}, experience with usage.
027   * <li>2013-03-24 Hartmut rewrite, create this class from MsgDispatchSystemOutErr
028   * <li>2013-01-26 Hartmut fine tuning
029   * <li>2012-01-07 Hartmut creation of MsgDispatchSystemOutErr, to support a simple usage of {@link MsgPrintStream} to redirect System.out and System.err.
030   * </ul>
031   * 
032   * <b>Copyright/Copyleft</b>:<br>
033   * For this source the LGPL Lesser General Public License,
034   * published by the Free Software Foundation is valid.
035   * It means:
036   * <ol>
037   * <li> You can use this source without any restriction for any desired purpose.
038   * <li> You can redistribute copies of this source to everybody.
039   * <li> Every user of this source, also the user of redistribute copies
040   *    with or without payment, must accept this license for further using.
041   * <li> But the LPGL is not appropriate for a whole software product,
042   *    if this source is only a part of them. It means, the user
043   *    must publish this part of source,
044   *    but doesn't need to publish the whole source of the own product.
045   * <li> You can study and modify (improve) this source
046   *    for own using or for redistribution, but you have to license the
047   *    modified sources likewise under this LGPL Lesser General Public License.
048   *    You mustn't delete this Copyright/Copyleft inscription in this source file.
049   * </ol>
050   * If you intent to use this source without publishing its usage, you can get
051   * a second license subscribing a special contract with the author. 
052   * 
053   * @author Hartmut Schorrig = hartmut.schorrig@vishia.de
054   */
055  public static final int version = 20130126;
056
057  
058  /**Indices to the output channels. */
059  public static final int ixMsgOutputStdOut = 0, ixMsgOutputStdErr = 1, ixMsgOutputFile = 2;
060  
061  
062  /**The converter from any output to a message.
063   * Note that you can invoke {@link MsgPrintStream#setMsgGroupIdent(String, int, int)} to manipulate the building
064   * of the ident numbers.
065   */
066  public final MsgPrintStream printOut, printErr;
067  
068  private final TimeZone timeZoneForFile = TimeZone.getTimeZone("GMT");
069  
070  /**The output channels to console. */
071  public final LogMessage cmdlineOut, cmdlineErr;
072  
073  private final MsgConfig msgConfig = new MsgConfig();
074  
075  /**Initializes the redirection of System.out and System.err in a full accessible way for Message Dispatching.
076   * @param identStartOut  The message number of auto-generate numbers for first System.out
077   * @param identStartErr  The message number of auto-generate numbers for first System.err
078   *   if -1 then the System.err is not overridden.
079   * @param sizeNoGroup    max. number of non-grouped messages
080   * @param sizeGroup      max. number of messages in a group. See {@link MsgPrintStream#MsgPrintStream(LogMessage, int, int, int)}
081   * @param mainCmd        An existing implementation especially {@link MainCmd} or its graphical derivation.
082   *   This parameter can be null if the MainCmd concept is not used. 
083   * @param maxDispatchEntries Further parameter see superclass {@link MsgDispatcher}
084   * @param maxQueue
085   * @param maxOutputs
086   * @param msgIdentQueueOverflow
087   * @param runNoEntryMessage
088   */
089  public MsgRedirectConsole(int identStartOut, int identStartErr, int sizeNoGroup, int sizeGroup,
090      MainCmd mainCmd, 
091      int maxDispatchEntries, int maxQueue,
092      int maxOutputs, int msgIdentQueueOverflow,
093      Runnable runNoEntryMessage)
094  {
095    super(maxDispatchEntries, maxQueue, maxOutputs, 0,
096        msgIdentQueueOverflow, runNoEntryMessage);
097    Assert.check(true);  //capture the System.err and System.out for Assert.consoleOut(...).
098    printOut = new MsgPrintStream(this, identStartOut, sizeNoGroup, sizeGroup);
099    printErr = identStartErr >=0 ? new MsgPrintStream(this, identStartErr, sizeNoGroup, sizeGroup): null;
100    int maskOut = 0;
101    if(mainCmd == null){
102      cmdlineOut = new LogMessageStream(System.out);
103      cmdlineErr = new LogMessageStream(System.err);
104    } else { //use it from:
105      cmdlineOut = mainCmd.getLogMessageOutputConsole();
106      cmdlineErr = mainCmd.getLogMessageErrorConsole();
107      mainCmd.setLogMessageDestination(this);
108      setOutputRoutine(ixMsgOutputFile, "stdlog", true, true, mainCmd.getLogMessageOutputFile());
109    }
110    this.setOutputRoutine(ixMsgOutputStdOut, "stdout", false, true, cmdlineOut);
111    this.setOutputRoutine(ixMsgOutputStdErr, "stderr", false, true, cmdlineErr);
112    this.setOutputRange(0, 49999, maskOut | (1<<ixMsgOutputStdOut), MsgDispatcher.mSet, 0);
113    this.setOutputRange(50000, Integer.MAX_VALUE, maskOut | (1<<ixMsgOutputStdErr), MsgDispatcher.mSet, 0);
114    if(mainCmd == null){
115      this.setOutputRange(0, Integer.MAX_VALUE, 1<<ixMsgOutputFile, MsgDispatcher.mAdd, 0);
116    }
117    System.setOut(printOut.getPrintStreamLog(""));
118    if(printErr !=null){ System.setErr(printErr.getPrintStreamLog("")); }
119  }
120
121  
122  
123  /**Initializes the redirection of System.out and System.err in a simple standard way.
124   * @param fileOut A output for the Message Dispatcher which should act as the log file output.
125   *   It is assigned to the {@link #ixMsgOutputFile} for dispatching.
126   * @param addOutputs 0 or >0 if more outputs are considered.
127   * @param runNoEntryMessage Routine which is called on message overflow, can be null.
128   */
129  public MsgRedirectConsole(MainCmd mainCmd, int addOutputs, Runnable runNoEntryMessage)
130  { this(10000, 40000, 10000, 100, mainCmd, 10000, 1000, addOutputs+3, 9999, runNoEntryMessage);
131  }
132  
133  /**Initializes the redirection of System.out and System.err in the simplest standard way.
134   * All System.out and System.err will be completed with a timestamp and output then.
135   * You can use {@link #readConfig(File)} to set associations between the message start texts and numbers
136   * and switch messages on or off depending on their start texts. 
137   */
138  public MsgRedirectConsole()
139  { this(10000, 40000, 10000, 100, null, 10000, 1000, 3, 9999, null);
140  }
141  
142  public void setMsgIdents(MsgConfig src, String chnChars){
143    super.setMsgTextConverter(src);
144    printOut.setMsgIdents(src);
145    if(printErr !=null){
146      printOut.setMsgIdents(src);
147    }
148    src.setMsgDispaching(this, chnChars);
149  }
150  
151  public String readConfig(File fileConfig){ 
152    String sError = msgConfig.readConfig(fileConfig); 
153    if(sError == null){
154      setMsgIdents(msgConfig, "dfl");
155    } else {
156      System.err.println("MsgRedirectConsole.readConfig - syntax error; " + sError);
157    }
158    return sError;
159  }
160
161  
162}