View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *      http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  package org.apache.log4j.pattern;
    19
    20  import org.apache.log4j.helpers.LogLog;
    21  import org.apache.log4j.spi.LoggingEvent;
    22
    23  import java.text.SimpleDateFormat;
    24  import java.text.DateFormat;
    25  import java.text.FieldPosition;
    26  import java.text.ParsePosition;
    27  import java.util.Date;
    28  import java.util.TimeZone;
    29
    30
    31  /**
    32   * Convert and format the event's date in a StringBuffer.
    33   *
    34   * @author Ceki G&uuml;lc&uuml;
    35   */
    36  public final class DatePatternConverter extends LoggingEventPatternConverter {
    37      /**
    38       * ABSOLUTE string literal.
    39       */
    40    private static final String ABSOLUTE_FORMAT = "ABSOLUTE";
    41      /**
    42       * SimpleTimePattern for ABSOLUTE.
    43       */
    44    private static final String ABSOLUTE_TIME_PATTERN = "HH:mm:ss,SSS";
    45
    46
    47      /**
    48       * DATE string literal.
    49       */
    50    private static final String DATE_AND_TIME_FORMAT = "DATE";
    51      /**
    52       * SimpleTimePattern for DATE.
    53       */
    54    private static final String DATE_AND_TIME_PATTERN = "dd MMM yyyy HH:mm:ss,SSS";
    55
    56      /**
    57       * ISO8601 string literal.
    58       */
    59    private static final String ISO8601_FORMAT = "ISO8601";
    60      /**
    61       * SimpleTimePattern for ISO8601.
    62       */
    63    private static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS";
    64    /**
    65     * Date format.
    66     */
    67    private final CachedDateFormat df;
    68
    69      /**
    70       * This class wraps a DateFormat and forces the time zone to the
    71       *   default time zone before each format and parse request.
    72       */
    73    private static class DefaultZoneDateFormat extends DateFormat {
    74       /**
    75        * Serialization version ID.
    76        */
    77       private static final long serialVersionUID = 1;
    78       /**
    79           * Wrapped instance of DateFormat.
    80           */
    81      private final DateFormat dateFormat;
    82
    83          /**
    84           * Construct new instance.
    85           * @param format format, may not be null.
    86           */
    87      public DefaultZoneDateFormat(final DateFormat format) {
    88          dateFormat = format;
    89      }
    90
    91          /**
    92           * @{inheritDoc}
    93           */
    94      public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) {
    95          dateFormat.setTimeZone(TimeZone.getDefault());
    96          return dateFormat.format(date, toAppendTo, fieldPosition);
    97      }
    98
    99          /**
    100          * @{inheritDoc}
    101          */
    102     public Date parse(String source, ParsePosition pos) {
    103         dateFormat.setTimeZone(TimeZone.getDefault());
    104         return dateFormat.parse(source, pos);
    105     }
    106   }
    107
    108   /**
    109    * Private constructor.
    110    * @param options options, may be null.
    111    */
    112   private DatePatternConverter(final String[] options) {
    113     super("Date", "date");
    114
    115     String patternOption;
    116
    117     if ((options == null) || (options.length == 0)) {
    118       // the branch could be optimized, but here we are making explicit
    119       // that null values for patternOption are allowed.
    120       patternOption = null;
    121     } else {
    122       patternOption = options[0];
    123     }
    124
    125     String pattern;
    126
    127     if (
    128       (patternOption == null)
    129         || patternOption.equalsIgnoreCase(ISO8601_FORMAT)) {
    130       pattern = ISO8601_PATTERN;
    131     } else if (patternOption.equalsIgnoreCase(ABSOLUTE_FORMAT)) {
    132       pattern = ABSOLUTE_TIME_PATTERN;
    133     } else if (patternOption.equalsIgnoreCase(DATE_AND_TIME_FORMAT)) {
    134       pattern = DATE_AND_TIME_PATTERN;
    135     } else {
    136       pattern = patternOption;
    137     }
    138
    139     int maximumCacheValidity = 1000;
    140     DateFormat simpleFormat = null;
    141
    142     try {
    143       simpleFormat = new SimpleDateFormat(pattern);
    144       maximumCacheValidity = CachedDateFormat.getMaximumCacheValidity(pattern);
    145     } catch (IllegalArgumentException e) {
    146         LogLog.warn(
    147           "Could not instantiate SimpleDateFormat with pattern "
    148           + patternOption, e);
    149
    150       // default to the ISO8601 format
    151       simpleFormat = new SimpleDateFormat(ISO8601_PATTERN);
    152     }
    153
    154     // if the option list contains a TZ option, then set it.
    155     if ((options != null) && (options.length > 1)) {
    156       TimeZone tz = TimeZone.getTimeZone((String) options[1]);
    157       simpleFormat.setTimeZone(tz);
    158     } else {
    159       simpleFormat = new DefaultZoneDateFormat(simpleFormat);
    160     }
    161
    162     df = new CachedDateFormat(simpleFormat, maximumCacheValidity);
    163   }
    164
    165   /**
    166    * Obtains an instance of pattern converter.
    167    * @param options options, may be null.
    168    * @return instance of pattern converter.
    169    */
    170   public static DatePatternConverter newInstance(
    171     final String[] options) {
    172     return new DatePatternConverter(options);
    173   }
    174
    175   /**
    176    * {@inheritDoc}
    177    */
    178   public void format(final LoggingEvent event, final StringBuffer output) {
    179     synchronized(this) {
    180     	df.format(event.timeStamp, output);
    181     }
    182   }
    183
    184   /**
    185    * {@inheritDoc}
    186    */
    187   public void format(final Object obj, final StringBuffer output) {
    188     if (obj instanceof Date) {
    189       format((Date) obj, output);
    190     }
    191
    192     super.format(obj, output);
    193   }
    194
    195   /**
    196    * Append formatted date to string buffer.
    197    * @param date date
    198    * @param toAppendTo buffer to which formatted date is appended.
    199    */
    200   public void format(final Date date, final StringBuffer toAppendTo) {
    201     synchronized(this) {
    202     	df.format(date.getTime(), toAppendTo);
    203     }
    204   }
    205 }