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      /**
35       * ABSOLUTE string literal.
36       */
37      private static final String ABSOLUTE_FORMAT = "ABSOLUTE";
38  
39      /**
40       * COMPACT string literal.
41       */
42      private static final String COMPACT_FORMAT = "COMPACT";
43  
44      /**
45       * SimpleTimePattern for ABSOLUTE.
46       */
47      private static final String ABSOLUTE_TIME_PATTERN = "HH:mm:ss,SSS";
48  
49      /**
50       * DATE string literal.
51       */
52      private static final String DATE_AND_TIME_FORMAT = "DATE";
53  
54      /**
55       * SimpleTimePattern for DATE.
56       */
57      private static final String DATE_AND_TIME_PATTERN = "dd MMM yyyy HH:mm:ss,SSS";
58  
59      /**
60       * ISO8601 string literal.
61       */
62      private static final String ISO8601_FORMAT = "ISO8601";
63  
64      /**
65       * ISO8601_BASIC string literal.
66       */
67      private static final String ISO8601_BASIC_FORMAT = "ISO8601_BASIC";
68  
69      /**
70       * SimpleTimePattern for ISO8601.
71       */
72      private static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS";
73  
74      /**
75       * SimpleTimePattern for ISO8601_BASIC.
76       */
77      private static final String ISO8601_BASIC_PATTERN = "yyyyMMdd HHmmss,SSS";
78  
79      /**
80       * SimpleTimePattern for COMPACT.
81       */
82      private static final String COMPACT_PATTERN = "yyyyMMddHHmmssSSS";
83  
84      /**
85       * Date format.
86       */
87      private String cachedDate;
88  
89      private long lastTimestamp;
90  
91      private final SimpleDateFormat simpleFormat;
92  
93      /**
94       * Private constructor.
95       *
96       * @param options options, may be null.
97       */
98      private DatePatternConverter(final String[] options) {
99          super("Date", "date");
100 
101         String patternOption;
102 
103         if (options == null || options.length == 0) {
104             // the branch could be optimized, but here we are making explicit
105             // that null values for patternOption are allowed.
106             patternOption = null;
107         } else {
108             patternOption = options[0];
109         }
110 
111         String pattern;
112 
113         if (patternOption == null || patternOption.equalsIgnoreCase(ISO8601_FORMAT)) {
114             pattern = ISO8601_PATTERN;
115         } else if (patternOption.equalsIgnoreCase(ISO8601_BASIC_FORMAT)) {
116             pattern = ISO8601_BASIC_PATTERN;
117         } else if (patternOption.equalsIgnoreCase(ABSOLUTE_FORMAT)) {
118             pattern = ABSOLUTE_TIME_PATTERN;
119         } else if (patternOption.equalsIgnoreCase(DATE_AND_TIME_FORMAT)) {
120             pattern = DATE_AND_TIME_PATTERN;
121         } else if (patternOption.equalsIgnoreCase(COMPACT_FORMAT)) {
122             pattern = COMPACT_PATTERN;
123         } else {
124             pattern = patternOption;
125         }
126 
127         SimpleDateFormat tempFormat;
128 
129         try {
130             tempFormat = new SimpleDateFormat(pattern);
131         } catch (final IllegalArgumentException e) {
132             LOGGER.warn("Could not instantiate SimpleDateFormat with pattern " + patternOption, e);
133 
134             // default to the ISO8601 format
135             tempFormat = new SimpleDateFormat(ISO8601_PATTERN);
136         }
137 
138         // if the option list contains a TZ option, then set it.
139         if (options != null && options.length > 1) {
140             final TimeZone tz = TimeZone.getTimeZone(options[1]);
141             tempFormat.setTimeZone(tz);
142         }
143         simpleFormat = tempFormat;
144     }
145 
146     /**
147      * Obtains an instance of pattern converter.
148      *
149      * @param options options, may be null.
150      * @return instance of pattern converter.
151      */
152     public static DatePatternConverter newInstance(final String[] options) {
153         return new DatePatternConverter(options);
154     }
155 
156     /**
157      * {@inheritDoc}
158      */
159     @Override
160     public void format(final LogEvent event, final StringBuilder output) {
161         final long timestamp = event.getMillis();
162 
163         synchronized (this) {
164             if (timestamp != lastTimestamp) {
165                 lastTimestamp = timestamp;
166                 cachedDate = simpleFormat.format(timestamp);
167             }
168         }
169         output.append(cachedDate);
170     }
171 
172     public void format(final StringBuilder toAppendTo, final Object... objects) {
173         for (final Object obj : objects) {
174             if (obj instanceof Date) {
175                 format(obj, toAppendTo);
176                 break;
177             }
178         }
179     }
180 
181     /**
182      * {@inheritDoc}
183      */
184     @Override
185     public void format(final Object obj, final StringBuilder output) {
186         if (obj instanceof Date) {
187             format((Date) obj, output);
188         }
189 
190         super.format(obj, output);
191     }
192 
193     /**
194      * Append formatted date to string buffer.
195      *
196      * @param date       date
197      * @param toAppendTo buffer to which formatted date is appended.
198      */
199     public void format(final Date date, final StringBuilder toAppendTo) {
200         synchronized (this) {
201             toAppendTo.append(simpleFormat.format(date.getTime()));
202         }
203     }
204 
205     public String getPattern() {
206         return simpleFormat.toPattern();
207     }
208 
209 }