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 java.text.SimpleDateFormat;
20  import java.util.Date;
21  import java.util.TimeZone;
22  
23  import org.apache.logging.log4j.core.LogEvent;
24  import org.apache.logging.log4j.core.config.plugins.Plugin;
25  
26  /**
27   * Convert and format the event's date in a StringBuilder.
28   */
29  @Plugin(name = "DatePatternConverter", category = "Converter")
30  @ConverterKeys({ "d", "date" })
31  public final class DatePatternConverter extends LogEventPatternConverter implements ArrayPatternConverter {
32  
33      private abstract static class Formatter {
34          abstract String format(long time);
35  
36          public String toPattern() {
37              return null;
38          }
39      }
40  
41      private static class PatternFormatter extends Formatter {
42          private final SimpleDateFormat simpleDateFormat;
43  
44          PatternFormatter(final SimpleDateFormat simpleDateFormat) {
45              this.simpleDateFormat = simpleDateFormat;
46          }
47  
48          @Override
49          String format(final long time) {
50              return simpleDateFormat.format(Long.valueOf(time));
51          }
52  
53          @Override
54          public String toPattern() {
55              return simpleDateFormat.toPattern();
56          }
57      }
58  
59      private static class UnixFormatter extends Formatter {
60  
61          @Override
62          String format(final long time) {
63              return Long.toString(time / 1000);
64          }
65  
66      }
67  
68      private static class UnixMillisFormatter extends Formatter {
69  
70          @Override
71          String format(final long time) {
72              return Long.toString(time);
73          }
74  
75      }
76  
77      /**
78       * ABSOLUTE string literal.
79       */
80      private static final String ABSOLUTE_FORMAT = "ABSOLUTE";
81  
82      /**
83       * SimpleTimePattern for ABSOLUTE.
84       */
85      private static final String ABSOLUTE_TIME_PATTERN = "HH:mm:ss,SSS";
86  
87      /**
88       * COMPACT string literal.
89       */
90      private static final String COMPACT_FORMAT = "COMPACT";
91  
92      /**
93       * SimpleTimePattern for COMPACT.
94       */
95      private static final String COMPACT_PATTERN = "yyyyMMddHHmmssSSS";
96  
97      /**
98       * DATE string literal.
99       */
100     private static final String DATE_AND_TIME_FORMAT = "DATE";
101 
102     /**
103      * SimpleTimePattern for DATE.
104      */
105     private static final String DATE_AND_TIME_PATTERN = "dd MMM yyyy HH:mm:ss,SSS";
106 
107     /**
108      * ISO8601_BASIC string literal.
109      */
110     private static final String ISO8601_BASIC_FORMAT = "ISO8601_BASIC";
111 
112     /**
113      * SimpleTimePattern for ISO8601_BASIC.
114      */
115     private static final String ISO8601_BASIC_PATTERN = "yyyyMMdd HHmmss,SSS";
116 
117     /**
118      * ISO8601 string literal.
119      */
120     private static final String ISO8601_FORMAT = "ISO8601";
121 
122     /**
123      * SimpleTimePattern for ISO8601.
124      */
125     private static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS";
126 
127     /**
128      * UNIX formatter in seconds (standard).
129      */
130     private static final String UNIX_FORMAT = "UNIX";
131 
132     /**
133      * UNIX formatter in milliseconds
134      */
135     private static final String UNIX_MILLIS_FORMAT = "UNIX_MILLIS";
136 
137     /**
138      * Obtains an instance of pattern converter.
139      * 
140      * @param options
141      *            options, may be null.
142      * @return instance of pattern converter.
143      */
144     public static DatePatternConverter newInstance(final String[] options) {
145         return new DatePatternConverter(options);
146     }
147 
148     /**
149      * Date format.
150      */
151     private String cachedDateString;
152 
153     private final Formatter formatter;
154 
155     private long lastTimestamp;
156 
157     /**
158      * Private constructor.
159      * 
160      * @param options
161      *            options, may be null.
162      */
163     private DatePatternConverter(final String[] options) {
164         super("Date", "date");
165 
166         // null patternOption is OK.
167         final String patternOption = options != null && options.length > 0 ? options[0] : null;
168 
169         String pattern = null;
170         Formatter tempFormatter = null;
171 
172         if (patternOption == null || patternOption.equalsIgnoreCase(ISO8601_FORMAT)) {
173             pattern = ISO8601_PATTERN;
174         } else if (patternOption.equalsIgnoreCase(ISO8601_BASIC_FORMAT)) {
175             pattern = ISO8601_BASIC_PATTERN;
176         } else if (patternOption.equalsIgnoreCase(ABSOLUTE_FORMAT)) {
177             pattern = ABSOLUTE_TIME_PATTERN;
178         } else if (patternOption.equalsIgnoreCase(DATE_AND_TIME_FORMAT)) {
179             pattern = DATE_AND_TIME_PATTERN;
180         } else if (patternOption.equalsIgnoreCase(COMPACT_FORMAT)) {
181             pattern = COMPACT_PATTERN;
182         } else if (patternOption.equalsIgnoreCase(UNIX_FORMAT)) {
183             tempFormatter = new UnixFormatter();
184         } else if (patternOption.equalsIgnoreCase(UNIX_MILLIS_FORMAT)) {
185             tempFormatter = new UnixMillisFormatter();
186         } else {
187             pattern = patternOption;
188         }
189 
190         if (pattern != null) {
191             SimpleDateFormat tempFormat;
192 
193             try {
194                 tempFormat = new SimpleDateFormat(pattern);
195             } catch (final IllegalArgumentException e) {
196                 LOGGER.warn("Could not instantiate SimpleDateFormat with pattern " + patternOption, e);
197 
198                 // default to the ISO8601 format
199                 tempFormat = new SimpleDateFormat(ISO8601_PATTERN);
200             }
201 
202             // if the option list contains a TZ option, then set it.
203             if (options != null && options.length > 1) {
204                 final TimeZone tz = TimeZone.getTimeZone(options[1]);
205                 tempFormat.setTimeZone(tz);
206             }
207             tempFormatter = new PatternFormatter(tempFormat);
208         }
209         formatter = tempFormatter;
210     }
211 
212     /**
213      * Append formatted date to string buffer.
214      * 
215      * @param date
216      *            date
217      * @param toAppendTo
218      *            buffer to which formatted date is appended.
219      */
220     public void format(final Date date, final StringBuilder toAppendTo) {
221         synchronized (this) {
222             toAppendTo.append(formatter.format(date.getTime()));
223         }
224     }
225 
226     /**
227      * {@inheritDoc}
228      */
229     @Override
230     public void format(final LogEvent event, final StringBuilder output) {
231         final long timestamp = event.getTimeMillis();
232 
233         synchronized (this) {
234             if (timestamp != lastTimestamp) {
235                 lastTimestamp = timestamp;
236                 cachedDateString = formatter.format(timestamp);
237             }
238         }
239         output.append(cachedDateString);
240     }
241 
242     /**
243      * {@inheritDoc}
244      */
245     @Override
246     public void format(final Object obj, final StringBuilder output) {
247         if (obj instanceof Date) {
248             format((Date) obj, output);
249         }
250         super.format(obj, output);
251     }
252 
253     @Override
254     public void format(final StringBuilder toAppendTo, final Object... objects) {
255         for (final Object obj : objects) {
256             if (obj instanceof Date) {
257                 format(obj, toAppendTo);
258                 break;
259             }
260         }
261     }
262 
263     /**
264      * Gets the pattern string describing this date format.
265      * 
266      * @return the pattern string describing this date format.
267      */
268     public String getPattern() {
269         return formatter.toPattern();
270     }
271 
272 }