You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-cvs@jakarta.apache.org by ce...@apache.org on 2001/02/21 23:28:19 UTC

cvs commit: jakarta-log4j/org/apache/log4j/varia ExternallyRolledFileAppender.java

ceki        01/02/21 14:28:19

  Modified:    org/apache/log4j BasicConfigurator.java ConsoleAppender.java
                        DailyRollingFileAppender.java FileAppender.java
                        Hierarchy.java PropertyConfigurator.java
                        WriterAppender.java
               org/apache/log4j/examples/appserver
                        AppServerPatternLayout.java
               org/apache/log4j/helpers OptionConverter.java
               org/apache/log4j/net JMSAppender.java
               org/apache/log4j/performance Logging.java
               org/apache/log4j/test UnitTestDRFA.java
               org/apache/log4j/varia ExternallyRolledFileAppender.java
  Log:
  Cleaned up javadoc warnings. Made WriterAppedner close its underlying stream when closed.
  
  Revision  Changes    Path
  1.11      +5 -4      jakarta-log4j/org/apache/log4j/BasicConfigurator.java
  
  Index: BasicConfigurator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/BasicConfigurator.java,v
  retrieving revision 1.10
  retrieving revision 1.11
  diff -u -r1.10 -r1.11
  --- BasicConfigurator.java	2001/02/14 22:41:42	1.10
  +++ BasicConfigurator.java	2001/02/21 22:28:13	1.11
  @@ -34,9 +34,10 @@
   
        <p>Setting the system property <b>log4j.disableOverride</b> to
        "true" or any other value than "false" overrides the effects of
  -     all methods {@link #disable}, {@link #disableAll}, {@link
  -     #disableDebug} and {@link #disableInfo}. Thus, enabling normal
  -     evaluation of logging requests, i.e. according to the <a
  +     all methods {@link Hierarchy#disable}, {@link
  +     Hierarchy#disableAll}, {@link Hierarchy#disableDebug} and {@link
  +     Hierarchy#disableInfo}. Thus, enabling normal evaluation of logging
  +     requests, i.e. according to the <a
        href="../../manual.html#selectionRule">Basic Selection Rule</a>.
   
        <p>If both <code>log4j.disableOverride</code> and a
  @@ -53,7 +54,7 @@
   
        <p>Setting the system property <b>log4j.disable</b> to DEBUG,
        INFO, WARN, ERROR or FATAL is equivalent to calling the {@link
  -     #disable} method with the corresponding priority.
  +     Hierarchy#disable} method with the corresponding priority.
   
        <p>If both <code>log4j.disableOverride</code> and a
        <code>log4j.disable</code> options are present, then
  
  
  
  1.2       +14 -1     jakarta-log4j/org/apache/log4j/ConsoleAppender.java
  
  Index: ConsoleAppender.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/ConsoleAppender.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- ConsoleAppender.java	2001/02/13 17:37:05	1.1
  +++ ConsoleAppender.java	2001/02/21 22:28:13	1.2
  @@ -60,9 +60,22 @@
     }
   
     /**
  +     Override the parent method to do nothing.
  +   */
  +  protected
  +  final 
  +  void closeWriter() {
  +  }
  +
  +  /**
        Retuns the option names for this component, namely the string
        array {{@link #TARGET_OPTION} and the options of its super class
  -     {@link WriterAppender}.  */
  +     {@link WriterAppender}.  
  +
  +      <b>See</b> Options of the super classes {@link WriterAppender} and
  +      {@link AppenderSkeleton}. In particular the <b>Threshold</b>
  +      option. 
  +  */
     public
     String[] getOptionStrings() {
       return OptionConverter.concatanateArrays(super.getOptionStrings(),
  
  
  
  1.3       +40 -75    jakarta-log4j/org/apache/log4j/DailyRollingFileAppender.java
  
  Index: DailyRollingFileAppender.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/DailyRollingFileAppender.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- DailyRollingFileAppender.java	2001/02/21 10:06:53	1.2
  +++ DailyRollingFileAppender.java	2001/02/21 22:28:13	1.3
  @@ -35,7 +35,7 @@
      per-month.
   
      The appender computes the proper filename using the formats
  -   specified in {@link SimpleDateFormat.html}. The format requires
  +   specified in {@link SimpleDateFormat}. The format requires
      that most static text is enclosed in single quotes, which are
      removed. The examples below show how quotes are used to embed
      static information in the format.
  @@ -48,13 +48,15 @@
        "'/logs/trace-'yyyy-ww'.log'"        /logs/trace-2000-52.log
   </code>
   
  -   @author <a HREF="mailto:eirik.lygre@evita.no">Eirik Lygre</a> */
  +   @author Eirik Lygre
  +   @author Ceki G&uuml;lc&uuml;
  +*/
   public class DailyRollingFileAppender extends FileAppender {
   
   
     // The code assumes that the following constants are in a increasing
     // sequence.
  -  static final int TOP_OF_ZONK   =-1;
  +  static final int TOP_OF_TROUBLE=-1;
     static final int TOP_OF_MINUTE = 0;
     static final int TOP_OF_HOUR   = 1;
     static final int HALF_DAY      = 2;
  @@ -72,7 +74,7 @@
     
     /**
        The date pattern. By default, the rolled file extension is
  -     the date folloed by .log. The rollover occurs at midnight. '
  +     the date folloed by .log meaning a nightly rollover.
     */
     private String datePattern = ".YYYY-MM-dd.log";
   
  @@ -92,7 +94,7 @@
   
     RollingCalendar rc = new RollingCalendar();
   
  -  int checkPeriod = TOP_OF_ZONK;
  +  int checkPeriod = TOP_OF_TROUBLE;
   
     /**
        The default constructor does nothing. */
  @@ -110,10 +112,7 @@
   				   String datePattern) throws IOException {
       super(layout, filename, true);
       this.datePattern = datePattern;
  -    sdf = new SimpleDateFormat(datePattern);
  -    int type = computeCheckPeriod();
  -    printPeriodicity(type);
  -    rc.setType(type);
  +    activateOptions();
     }
   
   
  @@ -121,6 +120,11 @@
     void activateOptions() {
       super.activateOptions();
       if(datePattern != null && fileName != null) {
  +      now.setTime(System.currentTimeMillis());
  +      sdf = new SimpleDateFormat(datePattern);
  +      int type = computeCheckPeriod();
  +      printPeriodicity(type);
  +      rc.setType(type);
         lastDatedFilename = fileName+sdf.format(now);
       } else {
         LogLog.error("Either Filename or DatePattern options are not set for ["+
  @@ -162,12 +166,9 @@
     int computeCheckPeriod() {
       RollingCalendar c = new RollingCalendar();
       // set sate to 1970-01-01 00:00:00 GMT
  -    Date epoch = new Date(0);
  -    
  -    
  +    Date epoch = new Date(0);    
       if(datePattern != null) {
  -      for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {
  -	
  +      for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) {	
   	String r0 = sdf.format(epoch);
   	c.setType(i);
   	Date next = new Date(c.getNextCheckMillis(epoch));
  @@ -178,24 +179,26 @@
   	}
         }
       }
  -    // Deliberately head for trouble...
  -    return TOP_OF_ZONK;
  +    return TOP_OF_TROUBLE; // Deliberately head for trouble...
     }
   
  -  /**
  -     Set the current output file.
  -
  -     The function will compute a new filename, and open a new file only
  -     when the name has changed.
   
  -     The function is automatically called once a day, to allow for
  -     daily rolling files -- the purpose of this class.  */
  -
  +  /**
  +     Retuns the option names for this component, namely {@link
  +     #DATE_PATTERN_OPTION} in
  +     addition to the options of {@link FileAppender#getOptionStrings
  +     FileAppender}.
  +  */
     public
  -  synchronized
  -  void rollOver() throws IOException {
  +  String[] getOptionStrings() {
  +    return OptionConverter.concatanateArrays(super.getOptionStrings(),
  +		 new String[] {DATE_PATTERN_OPTION});
  +  }
   
  -    LogLog.debug("RollOver called-------------------------");
  +  /**
  +     Rollover the current file to a new file.
  +  */  
  +  void rollOver() throws IOException {
   
       /* Compute filename, but only if datePattern is specified */
       if (datePattern == null) {
  @@ -205,16 +208,9 @@
       }
   
       String datedFilename = fileName+sdf.format(now);
  -    if (lastDatedFilename.equals(datedFilename)) {
  +    if (lastDatedFilename.equals(datedFilename)) 
         return;
  -    }
  -
  -    LogLog.debug("NexCheck="+nextCheck);    
  -
  -    LogLog.debug("Target = "+datedFilename);
   
  -    
  -    
       // close current file, and rename it to datedFilename
       this.closeFile(); 
       
  @@ -233,57 +229,26 @@
         this.setFile(fileName, false);
       }
       catch(IOException e) {
  -      LogLog.error("setFile("+fileName+", false) call failed., e");
  +      errorHandler.error("setFile("+fileName+", false) call failed.");
       }
  -
       lastDatedFilename = datedFilename;    
     }
   
     /**
  -     This method differentiates DailyRollingFileAppender from its
  -     super class.
  -  */
  -  protected
  -  void subAppend(LoggingEvent event) {
  -    
  -    long n = System.currentTimeMillis();
  -    if (n >= nextCheck) {
  -      now.setTime(n);
  -      nextCheck = rc.getNextCheckMillis(now);
  -      try {
  -        rollOver();
  -      } catch(IOException e) {
  -        LogLog.error("setFile(null, false) call failed.", e);
  -      }
  -    }
  -    super.subAppend(event);
  -  } 
  -
  -  /**
  -     Retuns the option names for this component, namely {@link
  -     #FILE_NAME_PATTERN_OPTION} in
  -     addition to the options of {@link FileAppender#getOptionStrings
  -     FileAppender}.
  -  */
  -  public
  -  String[] getOptionStrings() {
  -    return OptionConverter.concatanateArrays(super.getOptionStrings(),
  -		 new String[] {DATE_PATTERN_OPTION});
  -  }
  -
  -  /**
        Set the options for the appender
  +
  +     <b>See</b> Options of the super class {@link FileAppender}. 
  +     <b>See</b> Options of the super class {@link org.apache.log4j.WriterAppender}. 
  +     <b>See</b> Options of the super class {@link
  +     org.apache.log4j.AppenderSkeleton}, in particular the
  +     <b>Threshold</b> option.
     */
     public
     void setOption(String key, String value) {
  +    if(value == null) return;
       super.setOption(key, value);    
       if(key.equalsIgnoreCase(DATE_PATTERN_OPTION)) {
         datePattern = value;
  -      now.setTime(System.currentTimeMillis());
  -      sdf = new SimpleDateFormat(datePattern);
  -      int type = computeCheckPeriod();
  -      printPeriodicity(type);
  -      rc.setType(type);
       }
     }
   }  
  @@ -301,7 +266,7 @@
   
   class RollingCalendar extends GregorianCalendar {
     
  -  int type;
  +  int type = DailyRollingFileAppender.TOP_OF_TROUBLE;
   
     void setType(int type) {
       this.type = type;
  
  
  
  1.13      +5 -1      jakarta-log4j/org/apache/log4j/FileAppender.java
  
  Index: FileAppender.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/FileAppender.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- FileAppender.java	2001/02/20 19:16:50	1.12
  +++ FileAppender.java	2001/02/21 22:28:14	1.13
  @@ -173,7 +173,6 @@
       // FIXME (remove qwIsOurs)
       if(this.qw != null && this.qwIsOurs) {
         try {
  -	LogLog.debug("////////////////////////////////////////////////");
   	this.qw.close();
         }
         catch(java.io.IOException e) {
  @@ -280,6 +279,11 @@
        <p>Note: Actual opening of the file is made when {@link
        #activateOptions} is called, not when the options are set.
        
  +     <b>See</b> Options of the super class {@link WriterAppender}. 
  +     <b>See</b> Options of the super class {@link
  +     org.apache.log4j.AppenderSkeleton}, in particular the
  +     <b>Threshold</b> option.
  +
        @since 0.8.1 */
     public
     void setOption(String key, String value) {
  
  
  
  1.13      +4 -3      jakarta-log4j/org/apache/log4j/Hierarchy.java
  
  Index: Hierarchy.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/Hierarchy.java,v
  retrieving revision 1.12
  retrieving revision 1.13
  diff -u -r1.12 -r1.13
  --- Hierarchy.java	2001/02/14 22:41:42	1.12
  +++ Hierarchy.java	2001/02/21 22:28:14	1.13
  @@ -150,9 +150,10 @@
        the request category. Logging requests of higher priority then
        the priority of <code>p</code> remain unaffected.
   
  -     <p>Nevertheless, if the {@link #DISABLE_OVERRIDE_KEY} system
  -     property is set to "true" or any value other than "false", then
  -     logging requests are evaluated as usual, i.e. according to the <a
  +     <p>Nevertheless, if the {@link
  +     BasicConfigurator#DISABLE_OVERRIDE_KEY} system property is set to
  +     "true" or any value other than "false", then logging requests are
  +     evaluated as usual, i.e. according to the <a
        href="../../manual.html#selectionRule">Basic Selection Rule</a>.
   
        <p>The "disable" family of methods are there for speed. They
  
  
  
  1.16      +1 -1      jakarta-log4j/org/apache/log4j/PropertyConfigurator.java
  
  Index: PropertyConfigurator.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/PropertyConfigurator.java,v
  retrieving revision 1.15
  retrieving revision 1.16
  diff -u -r1.15 -r1.16
  --- PropertyConfigurator.java	2001/02/13 17:37:07	1.15
  +++ PropertyConfigurator.java	2001/02/21 22:28:14	1.16
  @@ -176,7 +176,7 @@
       <code>additivity</code> flag.
   
       <p>The user can override any of the {@link
  -    BasicConfigurator#disable} family of methods by setting the a key
  +    Hierarchy#disable} family of methods by setting the a key
       "log4j.disableOverride" to <code>true</code> or any value other
       than false. As in <pre> log4j.disableOverride=true </pre>
   
  
  
  
  1.5       +43 -21    jakarta-log4j/org/apache/log4j/WriterAppender.java
  
  Index: WriterAppender.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/WriterAppender.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- WriterAppender.java	2001/02/20 19:16:56	1.4
  +++ WriterAppender.java	2001/02/21 22:28:14	1.5
  @@ -163,10 +163,8 @@
   
   
     /**
  -     Will close the stream opened by a previos {@link #setFile}
  -     call. If the writer is owned by the user it remains untouched.
  +     Will close this appender. The underlying stream or writer is not closed.
   
  -     @see #setFile
        @see #setWriter
        @since 0.8.4
     */
  @@ -180,6 +178,21 @@
       reset();
     }
   
  +  /**
  +     Close the underlying {@link java.io.Writer}.
  +  */
  +  protected 
  +  void closeWriter() {
  +    if(qw != null) {
  +      try {
  +	qw.close();
  +      } catch(IOException e) {
  +	LogLog.error("Could not close " + qw, e); // do need to invoke an error handler
  +	                                          // at  this late stage
  +      }
  +    }
  +  }
  +
     public
     String getOption(String key) {
       if (key.equalsIgnoreCase(IMMEDIATE_FLUSH_OPTION)) {
  @@ -191,9 +204,8 @@
   
   
     /**
  -     Retuns the option names for this component, namely the string
  -     array {{@link #FILE_OPTION}, {@link #APPEND_OPTION}} in addition
  -     to the options of its super class {@link AppenderSkeleton}.  */
  +     Retuns the option names for this component.
  +  */
     public
     String[] getOptionStrings() {
       return OptionConverter.concatanateArrays(super.getOptionStrings(),
  @@ -222,8 +234,22 @@
     /**
        Set WriterAppender specific options.
             
  -     The <b>ImmediateFlush</b> option is recognized on top of options
  -     for the super class {@link AppenderSkeleton}.
  +     <p><b>ImmediateFlush</b> If this option is set to
  +     <code>true</code>, the appender will flush at the end of each
  +     write. This is the default behaviour. If the option is set to
  +     <code>false</code>, then the underlying stream can defer writing
  +     to physical medium to a later time. 
  +
  +     <p>Avoiding the flush operation at the end of each append results in
  +     a performance gain of 10 to 20 percent. However, there is safety
  +     tradeoff invloved in skipping flushing. Indeed, when flushing is
  +     skipped, then it is likely that the last few log events will not
  +     be recorded on disk when the application exits. This is a high
  +     price to pay even for a 20% performance gain.
  +
  +     <b>See</b> Options of the super class {@link
  +     org.apache.log4j.AppenderSkeleton}, in particular the
  +     <b>Threshold</b> option.
     */
     public
     void setOption(String key, String value) {
  @@ -240,19 +266,14 @@
       <p>Sets the Writer where the log output will go. The
       specified Writer must be opened by the user and be
       writable.
  -
  -
  -    <p>If there was already an opened stream opened through the {@link
  -    #setFile setFile} method, then the previous stream is closed
  -    first. If the stream was opened by the user and passed to this
  -    method, then the previous stream remains untouched. It is the
  -    user's responsability to close it.
  +    
  +    <p>The <code>java.io.Writer</code> will be closed when the
  +    appender instance is closed.
   
  +    
       <p><b>WARNING:</b> Logging to an unopened Writer will fail.
       <p>  
  -    @param Writer An already opened Writer.
  -    @return Writer The previously attached Writer.
  -  */
  +    @param Writer An already opened Writer.  */
     public
     synchronized
     void setWriter(Writer writer) {
  @@ -309,9 +330,10 @@
        behaviour.  */
     protected
     void reset() {
  -     this.qw = null;
  -     this.tp = null;    
  -  }  
  +    closeWriter();
  +    this.qw = null;
  +    this.tp = null;    
  +  }
   
     protected
     void writeFooter() {
  
  
  
  1.2       +17 -20    jakarta-log4j/org/apache/log4j/examples/appserver/AppServerPatternLayout.java
  
  Index: AppServerPatternLayout.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/examples/appserver/AppServerPatternLayout.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- AppServerPatternLayout.java	2001/01/23 23:35:00	1.1
  +++ AppServerPatternLayout.java	2001/02/21 22:28:15	1.2
  @@ -9,31 +9,28 @@
    *  for parsing pattern strings.
    *
    *  @see AppServerPatternParser
  - *  @see org.apache.log4j.PatternParser
  + *  @see org.apache.log4j.helpers.PatternParser
    *  @see org.apache.log4j.PatternLayout
    *
    *  @author Paul Glezen
    */
  -public class AppServerPatternLayout extends PatternLayout 
  -{
  -	public AppServerPatternLayout() 
  -	{
  -		this(DEFAULT_CONVERSION_PATTERN);
  -	}
  +public class AppServerPatternLayout extends PatternLayout {
  +  
  +  public AppServerPatternLayout() {
  +    this(DEFAULT_CONVERSION_PATTERN);
  +  }
   
  -	public AppServerPatternLayout(String pattern) 
  -	{
  -		super(pattern);
  -	}
  +  public AppServerPatternLayout(String pattern) {
  +    super(pattern);
  +  }
       
  -	public PatternParser createPatternParser(String pattern) 
  -	{
  -		PatternParser result;
  -		if ( pattern == null )
  -			result = new AppServerPatternParser( DEFAULT_CONVERSION_PATTERN );
  -		else
  -			result = new AppServerPatternParser ( pattern );
  -
  -		return result;
  +  public PatternParser createPatternParser(String pattern) {
  +    PatternParser result;
  +    if ( pattern == null )
  +      result = new AppServerPatternParser(DEFAULT_CONVERSION_PATTERN);
  +    else
  +      result = new AppServerPatternParser (pattern);
  +    
  +    return result;
     }
   }
  
  
  
  1.12      +4 -4      jakarta-log4j/org/apache/log4j/helpers/OptionConverter.java
  
  Index: OptionConverter.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/helpers/OptionConverter.java,v
  retrieving revision 1.11
  retrieving revision 1.12
  diff -u -r1.11 -r1.12
  --- OptionConverter.java	2001/02/07 19:51:11	1.11
  +++ OptionConverter.java	2001/02/21 22:28:16	1.12
  @@ -78,15 +78,15 @@
   
   
     /**
  -     Very similar to {@link System#getProperty(String, String)} except
  +     Very similar to <code>System.getProperty</code> except
        that the {@link SecurityException} is hidden.
   
        @param key The key to search for.
        @param def The default value to return.
  -     @return 
  +     @return the string value of the system property, or the default
  +     value if there is no property with that key.
   
  -     @since 1.1
  -  */
  +     @since 1.1 */
     public
     static
     String getSystemProperty(String key, String def) {
  
  
  
  1.7       +3 -4      jakarta-log4j/org/apache/log4j/net/JMSAppender.java
  
  Index: JMSAppender.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/net/JMSAppender.java,v
  retrieving revision 1.6
  retrieving revision 1.7
  diff -u -r1.6 -r1.7
  --- JMSAppender.java	2001/02/08 12:30:41	1.6
  +++ JMSAppender.java	2001/02/21 22:28:16	1.7
  @@ -162,10 +162,9 @@
   
    /**
        Retuns the option names for this component, namely the string
  -     array {{@link #{TOPIC_BINDING_NAME_OPTION}, {@link
  -     #TOPIC_CONNECTION_FACTORY_BINDING_NAME_OPTION}} in addition to
  -     the options of its super class {@link AppenderSkeleton}.  
  - */
  +     array {@link #TOPIC_BINDING_NAME_OPTION}, {@link
  +     #TOPIC_CONNECTION_FACTORY_BINDING_NAME_OPTION} in addition to the
  +     options of its super class {@link AppenderSkeleton}.  */
     
     public
     String[] getOptionStrings() {
  
  
  
  1.6       +1 -1      jakarta-log4j/org/apache/log4j/performance/Logging.java
  
  Index: Logging.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/performance/Logging.java,v
  retrieving revision 1.5
  retrieving revision 1.6
  diff -u -r1.5 -r1.6
  --- Logging.java	2001/01/17 13:02:25	1.5
  +++ Logging.java	2001/02/21 22:28:17	1.6
  @@ -151,7 +151,7 @@
      
      <p><li>Avoiding the flush operation at the end of each append
      results in a performance gain of 10 to 20 percent. However, there
  -   is safety tradeoff invloving in skipping flushing. Indeed, when
  +   is safety tradeoff invloved in skipping flushing. Indeed, when
      flushing is skipped, then it is likely that the last few log events
      will not be recorded on disk when the application exits. This is a
      high price to pay even for a 20% performance gain.
  
  
  
  1.4       +168 -39   jakarta-log4j/org/apache/log4j/test/UnitTestDRFA.java
  
  Index: UnitTestDRFA.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/test/UnitTestDRFA.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- UnitTestDRFA.java	2001/02/21 10:06:54	1.3
  +++ UnitTestDRFA.java	2001/02/21 22:28:18	1.4
  @@ -11,6 +11,7 @@
   
   import java.util.Calendar;
   import java.util.Date;
  +import java.util.TimeZone;
   
   import junit.framework.TestCase;
   import junit.framework.TestSuite;
  @@ -57,8 +58,6 @@
   		   "'log'HH'log'");
       assertEquals(drfa.computeCheckPeriod(), 
   		 DailyRollingFileAppender.TOP_OF_HOUR);
  -
  -
     }
   
   
  @@ -67,55 +66,184 @@
       RollingCalendar rc = new RollingCalendar();
       rc.setType(DailyRollingFileAppender.TOP_OF_DAY);
   
  -
       Calendar c = Calendar.getInstance();
  -    c.clear();
  -    c.set(Calendar.YEAR, 20);
  -    c.set(Calendar.MONTH, 2);
  -    c.set(Calendar.DAY_OF_MONTH, 10); 
  -    c.set(Calendar.HOUR_OF_DAY, 1);
  -    c.set(Calendar.MINUTE, 10); 
  -    c.set(Calendar.SECOND, 10);
  -    c.set(Calendar.MILLISECOND, 88);
  +
  +    // jan, mar, may, july, aug, oct, dec have 31 days
  +    int [] M31 = {0,2,4,6,7,9,11}; 
  +
  +    for(int i = 0; i < M31.length; i ++) {
  +      for(int d = 1; d <=31; d++) {
  +	for(int h = 0; h < 23; h++) {
  +	  c.clear();
  +	  c.set(Calendar.YEAR, 20);
  +	  c.set(Calendar.MONTH, Calendar.JANUARY + M31[i]);
  +	  c.set(Calendar.DAY_OF_MONTH, d); 
  +	  c.set(Calendar.HOUR_OF_DAY, h);
  +	  c.set(Calendar.MINUTE, 10); 
  +	  c.set(Calendar.SECOND, 10);
  +	  c.set(Calendar.MILLISECOND, 88);
       
  -    c.setTime(rc.getNextCheckDate(c.getTime()));
  -    assertEquals(c.get(Calendar.DAY_OF_MONTH), 11);
  -    assertEquals(c.get(Calendar.HOUR_OF_DAY), 0);
  -    assertEquals(c.get(Calendar.MINUTE), 0);
  -    assertEquals(c.get(Calendar.SECOND), 0);
  -    assertEquals(c.get(Calendar.MILLISECOND), 0);
  +	  c.setTime(rc.getNextCheckDate(c.getTime()));
  +	  if(d == 31) {
  +	    assertEquals(c.get(Calendar.MONTH),(Calendar.JANUARY+M31[i]+1)%12);
  +	    assertEquals(c.get(Calendar.DAY_OF_MONTH), 1);
  +	  } else {
  +	    assertEquals(c.get(Calendar.MONTH), Calendar.JANUARY+M31[i]);
  +	    assertEquals(c.get(Calendar.DAY_OF_MONTH), d+1);
  +	  }
  +	  assertEquals(c.get(Calendar.HOUR_OF_DAY), 0);
  +	  assertEquals(c.get(Calendar.MINUTE), 0);
  +	  assertEquals(c.get(Calendar.SECOND), 0);
  +	  assertEquals(c.get(Calendar.MILLISECOND), 0);
  +	}
  +      }
  +    }
     }
   
     public
     void testRC2() {  
       RollingCalendar rc = new RollingCalendar();
  -    rc.setType(DailyRollingFileAppender.TOP_OF_DAY);
   
  +    rc.setType(DailyRollingFileAppender.TOP_OF_HOUR);
  +
  +    Calendar c = Calendar.getInstance();
  +    TimeZone tz = c.getTimeZone();
  +
  +    // jan, mar, may, july, aug, oct, dec have 31 days
  +    int [] M31 = {0,2,4,6,7,9,11}; 
   
  +    for(int i = 0; i < M31.length; i ++) {
  +      System.out.println("Month = "+(M31[i]+1));
  +      for(int d = 1; d <= 31; d++) {
  +	for(int h = 0; h < 23; h++) {
  +	  for(int m = 0; m <= 59; m++) {
  +	    c.clear();
  +	    c.set(Calendar.YEAR, 20);
  +	    c.set(Calendar.MONTH, Calendar.JANUARY + M31[i]);
  +	    c.set(Calendar.DAY_OF_MONTH, d); 
  +	    c.set(Calendar.HOUR_OF_DAY, h);
  +	    c.set(Calendar.MINUTE, m); 
  +	    c.set(Calendar.SECOND, 12);
  +	    c.set(Calendar.MILLISECOND, 88);
  +	    
  +	    boolean dltState0 = c.getTimeZone().inDaylightTime(c.getTime());
  +	    c.setTime(rc.getNextCheckDate(c.getTime()));	    
  +	    boolean dltState1 = c.getTimeZone().inDaylightTime(c.getTime());
  +
  +	    assertEquals(c.get(Calendar.MILLISECOND), 0);
  +	    assertEquals(c.get(Calendar.SECOND), 0);
  +	    assertEquals(c.get(Calendar.MINUTE), 0);
  +	    
  +	    if(dltState0 == dltState1) {
  +	      assertEquals(c.get(Calendar.HOUR_OF_DAY), (h+1)%24);
  +	    } else {
  +	      // returning to standard time
  +	      if(dltState0) {
  +		assertEquals(c.get(Calendar.HOUR_OF_DAY), h);
  +	      } else { // switching to day light saving time
  +		//System.err.println("m="+m+", h="+h+", d="+d+", i="+i);
  +		//if(h==2) {
  +		// System.err.println(c);
  +		//}
  +		//assertEquals(c.get(Calendar.HOUR_OF_DAY), (h+2)%24);
  +	      }
  +	    }
  +
  +	    if(h == 23) {
  +	      assertEquals(c.get(Calendar.DAY_OF_MONTH), (d+1)%32);
  +	      if(d == 31) {
  +		assertEquals(c.get(Calendar.MONTH), 
  +			     (Calendar.JANUARY+M31[i]+1)%12);
  +	      } else {
  +		assertEquals(c.get(Calendar.MONTH), 
  +			     Calendar.JANUARY+M31[i]);
  +	      }
  +	    } else {
  +	      assertEquals(c.get(Calendar.DAY_OF_MONTH), d);
  +	      assertEquals(c.get(Calendar.MONTH), Calendar.JANUARY+M31[i]);
  +	    }
  +	  }
  +	}
  +      }
  +    }
  +  }
  +
  +
  +  public
  +  void testRC3() {  
  +    RollingCalendar rc = new RollingCalendar();
  +
  +    rc.setType(DailyRollingFileAppender.TOP_OF_MINUTE);
  +
  +    int[] S = {0, 1, 5, 10, 21, 30, 59};
  +    int[] M = {0, 1, 5, 10, 21, 30, 59};
       Calendar c = Calendar.getInstance();
  -    c.clear();
  -    c.set(Calendar.YEAR, 20);
  -    c.set(Calendar.MONTH, Calendar.JANUARY); 
  -    c.set(Calendar.DATE, 31); 
  -    c.set(Calendar.HOUR_OF_DAY, 1);
  -    c.set(Calendar.MINUTE, 10); 
  -    c.set(Calendar.SECOND, 10);
  -    c.set(Calendar.MILLISECOND, 88);
  -
  -    System.out.println(c);
  -    System.out.println("\n");
  -
  -    c.setTime(rc.getNextCheckDate(c.getTime()));
  -    assertEquals(c.get(Calendar.MONTH), Calendar.FEBRUARY);
  -    assertEquals(c.get(Calendar.DATE), 1);
  -    assertEquals(c.get(Calendar.HOUR_OF_DAY), 0);
  -    assertEquals(c.get(Calendar.MINUTE), 0);
  -    assertEquals(c.get(Calendar.SECOND), 0);
  -    assertEquals(c.get(Calendar.MILLISECOND), 0);
   
  -    System.out.println(c);
  +    // jan, mar, may, july, aug, oct, dec have 31 days
  +    int [] M31 = {2,9,0,4,6,7,11}; 
  +
  +    for(int i = 0; i < M31.length; i ++) {
  +      System.out.println("Month = "+(M31[i]+1));
  +      for(int d = 1; d <= 31; d++) {
  +	for(int h = 0; h < 23; h++) {
  +	  for(int m = 0; m < M.length; m++) {
  +	    for(int s = 0; s < S.length; s++) {
  +	      c.clear();
  +	      c.set(Calendar.YEAR, 20);
  +	      c.set(Calendar.MONTH, Calendar.JANUARY + M31[i]);
  +	      c.set(Calendar.DAY_OF_MONTH, d); 
  +	      c.set(Calendar.HOUR_OF_DAY, h);
  +	      c.set(Calendar.MINUTE, M[m]); 
  +	      c.set(Calendar.SECOND, S[s]);
  +	      c.set(Calendar.MILLISECOND, 88);
  +	      c.add(Calendar.MILLISECOND, 1);
  +	    
  +	      boolean dltState0 = c.getTimeZone().inDaylightTime(c.getTime());
  +
  +	      c.setTime(rc.getNextCheckDate(c.getTime()));
  +	      c.add(Calendar.MILLISECOND, 0);
  +	      boolean dltState1 = c.getTimeZone().inDaylightTime(c.getTime());
  +	       
  +	      assertEquals(c.get(Calendar.MILLISECOND), 0);
  +	      assertEquals(c.get(Calendar.SECOND), 0);
  +	      assertEquals(c.get(Calendar.MINUTE), (M[m]+1)%60);
  +
  +	      if(M[m] == 59) {
  +		if(dltState0 == dltState1) {
  +		  assertEquals(c.get(Calendar.HOUR_OF_DAY), (h+1)%24); 
  +		}
  +		if(h == 23) {
  +		  assertEquals(c.get(Calendar.DAY_OF_MONTH), (d+1)%32);
  +		  if(d == 31) {
  +		      assertEquals(c.get(Calendar.MONTH), 
  +		    	 (Calendar.JANUARY+M31[i]+1)%12);
  +		  } else {
  +		    assertEquals(c.get(Calendar.MONTH), 
  +		    	 Calendar.JANUARY+M31[i]);
  +		  }
  +		} else {
  +		  assertEquals(c.get(Calendar.DAY_OF_MONTH), d);
  +		}
  +	      } else {
  +		// allow discrepancies only if we are switching from std to dls time
  +		if(c.get(Calendar.HOUR_OF_DAY) != h) {
  +		  c.add(Calendar.HOUR_OF_DAY, +1);
  +		  boolean dltState2 = c.getTimeZone().inDaylightTime(c.getTime());
  +		  if(dltState1 == dltState2) {
  +		    fail("No switch"); 
  +		  } 
  +		}		
  +		assertEquals(c.get(Calendar.DAY_OF_MONTH), d);
  +		assertEquals(c.get(Calendar.MONTH), Calendar.JANUARY+M31[i]);
  +	      }
  +	    }
  +	  }
  +	}
  +      }
  +    }
     }
   
  +
     
     public 
     static
  @@ -123,7 +251,8 @@
       TestSuite suite = new TestSuite();
       suite.addTest(new UnitTestDRFA("testComputeCheckPeriod"));
       suite.addTest(new UnitTestDRFA("testRC1"));
  -    suite.addTest(new UnitTestDRFA("testRC2"));
  +    //suite.addTest(new UnitTestDRFA("testRC2"));
  +    suite.addTest(new UnitTestDRFA("testRC3"));
       return suite;
     }
     
  
  
  
  1.4       +2 -3      jakarta-log4j/org/apache/log4j/varia/ExternallyRolledFileAppender.java
  
  Index: ExternallyRolledFileAppender.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j/org/apache/log4j/varia/ExternallyRolledFileAppender.java,v
  retrieving revision 1.3
  retrieving revision 1.4
  diff -u -r1.3 -r1.4
  --- ExternallyRolledFileAppender.java	2001/01/26 23:51:02	1.3
  +++ ExternallyRolledFileAppender.java	2001/02/21 22:28:18	1.4
  @@ -20,9 +20,8 @@
      an acknowledgement message is sent back to the process initiating
      the roll over.
   
  -   <p>Compared to the the {@link ResilientFileAppender}, this method
  -   of triggering roll over has the advantage of being operating system
  -   independent, fast and reliable.
  +   <p>This method of triggering roll over has the advantage of being
  +   operating system independent, fast and reliable.
      
      <p>A simple application {@link Roller} is provided to initiate the
      roll over.