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  package org.apache.logging.log4j.core.pattern;
18  
19  import org.apache.logging.log4j.core.LogEvent;
20  import org.apache.logging.log4j.core.config.plugins.Plugin;
21  
22  import java.text.SimpleDateFormat;
23  import java.util.Date;
24  import java.util.TimeZone;
25  
26  
27  /**
28   * Convert and format the event's date in a StringBuffer.
29   */
30  @Plugin(name = "DatePatternConverter", type = "Converter")
31  @ConverterKeys({"d", "date" })
32  public final class DatePatternConverter extends LogEventPatternConverter implements ArrayPatternConverter {
33      /**
34       * ABSOLUTE string literal.
35       */
36      private static final String ABSOLUTE_FORMAT = "ABSOLUTE";
37      /**
38       * SimpleTimePattern for ABSOLUTE.
39       */
40      private static final String ABSOLUTE_TIME_PATTERN = "HH:mm:ss,SSS";
41  
42  
43      /**
44       * DATE string literal.
45       */
46      private static final String DATE_AND_TIME_FORMAT = "DATE";
47      /**
48       * SimpleTimePattern for DATE.
49       */
50      private static final String DATE_AND_TIME_PATTERN = "dd MMM yyyy HH:mm:ss,SSS";
51  
52      /**
53       * ISO8601 string literal.
54       */
55      private static final String ISO8601_FORMAT = "ISO8601";
56      /**
57       * SimpleTimePattern for ISO8601.
58       */
59      private static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS";
60      /**
61       * Date format.
62       */
63      private String cachedDate;
64  
65      private long lastTimestamp;
66  
67      private SimpleDateFormat simpleFormat;
68  
69      /**
70       * Private constructor.
71       *
72       * @param options options, may be null.
73       */
74      private DatePatternConverter(final String[] options) {
75          super("Date", "date");
76  
77          String patternOption;
78  
79          if ((options == null) || (options.length == 0)) {
80              // the branch could be optimized, but here we are making explicit
81              // that null values for patternOption are allowed.
82              patternOption = null;
83          } else {
84              patternOption = options[0];
85          }
86  
87          String pattern;
88  
89          if (patternOption == null || patternOption.equalsIgnoreCase(ISO8601_FORMAT)) {
90              pattern = ISO8601_PATTERN;
91          } else if (patternOption.equalsIgnoreCase(ABSOLUTE_FORMAT)) {
92              pattern = ABSOLUTE_TIME_PATTERN;
93          } else if (patternOption.equalsIgnoreCase(DATE_AND_TIME_FORMAT)) {
94              pattern = DATE_AND_TIME_PATTERN;
95          } else {
96              pattern = patternOption;
97          }
98  
99          try {
100             simpleFormat = new SimpleDateFormat(pattern);
101         } catch (IllegalArgumentException e) {
102             LOGGER.warn("Could not instantiate SimpleDateFormat with pattern " + patternOption, e);
103 
104             // default to the ISO8601 format
105             simpleFormat = new SimpleDateFormat(ISO8601_PATTERN);
106         }
107 
108         // if the option list contains a TZ option, then set it.
109         if ((options != null) && (options.length > 1)) {
110             TimeZone tz = TimeZone.getTimeZone(options[1]);
111             simpleFormat.setTimeZone(tz);
112         }
113     }
114 
115     /**
116      * Obtains an instance of pattern converter.
117      *
118      * @param options options, may be null.
119      * @return instance of pattern converter.
120      */
121     public static DatePatternConverter newInstance(final String[] options) {
122         return new DatePatternConverter(options);
123     }
124 
125     /**
126      * {@inheritDoc}
127      */
128     public void format(final LogEvent event, final StringBuilder output) {
129         long timestamp = event.getMillis();
130 
131         synchronized (this) {
132             if (timestamp != lastTimestamp) {
133                 lastTimestamp = timestamp;
134                 cachedDate = simpleFormat.format(timestamp);
135             }
136         }
137         output.append(cachedDate);
138     }
139 
140     public void format(Object[] objects, final StringBuilder toAppendTo) {
141         for (Object obj : objects) {
142             if (obj instanceof Date) {
143                 format(obj, toAppendTo);
144                 break;
145             }
146         }
147     }
148 
149     /**
150      * {@inheritDoc}
151      */
152     public void format(final Object obj, final StringBuilder output) {
153         if (obj instanceof Date) {
154             format((Date) obj, output);
155         }
156 
157         super.format(obj, output);
158     }
159 
160     /**
161      * Append formatted date to string buffer.
162      *
163      * @param date       date
164      * @param toAppendTo buffer to which formatted date is appended.
165      */
166     public void format(final Date date, final StringBuilder toAppendTo) {
167         synchronized (this) {
168             toAppendTo.append(simpleFormat.format(date.getTime()));
169         }
170     }
171 
172     public String getPattern() {
173         return simpleFormat.toPattern();
174     }
175 
176 }