| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.log4j.pattern; |
| |
| import org.apache.log4j.helpers.LogLog; |
| import org.apache.log4j.spi.LoggingEvent; |
| |
| import java.text.SimpleDateFormat; |
| import java.text.DateFormat; |
| import java.text.FieldPosition; |
| import java.text.ParsePosition; |
| import java.util.Date; |
| import java.util.TimeZone; |
| |
| |
| /** |
| * Convert and format the event's date in a StringBuffer. |
| * |
| * @author Ceki Gülcü |
| */ |
| public final class DatePatternConverter extends LoggingEventPatternConverter { |
| /** |
| * ABSOLUTE string literal. |
| */ |
| private static final String ABSOLUTE_FORMAT = "ABSOLUTE"; |
| /** |
| * SimpleTimePattern for ABSOLUTE. |
| */ |
| private static final String ABSOLUTE_TIME_PATTERN = "HH:mm:ss,SSS"; |
| |
| |
| /** |
| * DATE string literal. |
| */ |
| private static final String DATE_AND_TIME_FORMAT = "DATE"; |
| /** |
| * SimpleTimePattern for DATE. |
| */ |
| private static final String DATE_AND_TIME_PATTERN = "dd MMM yyyy HH:mm:ss,SSS"; |
| |
| /** |
| * ISO8601 string literal. |
| */ |
| private static final String ISO8601_FORMAT = "ISO8601"; |
| /** |
| * SimpleTimePattern for ISO8601. |
| */ |
| private static final String ISO8601_PATTERN = "yyyy-MM-dd HH:mm:ss,SSS"; |
| /** |
| * Date format. |
| */ |
| private final CachedDateFormat df; |
| |
| /** |
| * This class wraps a DateFormat and forces the time zone to the |
| * default time zone before each format and parse request. |
| */ |
| private static class DefaultZoneDateFormat extends DateFormat { |
| /** |
| * Wrapped instance of DateFormat. |
| */ |
| private final DateFormat dateFormat; |
| |
| /** |
| * Construct new instance. |
| * @param format format, may not be null. |
| */ |
| public DefaultZoneDateFormat(final DateFormat format) { |
| dateFormat = format; |
| } |
| |
| /** |
| * @{inheritDoc} |
| */ |
| public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition fieldPosition) { |
| dateFormat.setTimeZone(TimeZone.getDefault()); |
| return dateFormat.format(date, toAppendTo, fieldPosition); |
| } |
| |
| /** |
| * @{inheritDoc} |
| */ |
| public Date parse(String source, ParsePosition pos) { |
| dateFormat.setTimeZone(TimeZone.getDefault()); |
| return dateFormat.parse(source, pos); |
| } |
| } |
| |
| /** |
| * Private constructor. |
| * @param options options, may be null. |
| */ |
| private DatePatternConverter(final String[] options) { |
| super("Date", "date"); |
| |
| String patternOption; |
| |
| if ((options == null) || (options.length == 0)) { |
| // the branch could be optimized, but here we are making explicit |
| // that null values for patternOption are allowed. |
| patternOption = null; |
| } else { |
| patternOption = options[0]; |
| } |
| |
| String pattern; |
| |
| if ( |
| (patternOption == null) |
| || patternOption.equalsIgnoreCase(ISO8601_FORMAT)) { |
| pattern = ISO8601_PATTERN; |
| } else if (patternOption.equalsIgnoreCase(ABSOLUTE_FORMAT)) { |
| pattern = ABSOLUTE_TIME_PATTERN; |
| } else if (patternOption.equalsIgnoreCase(DATE_AND_TIME_FORMAT)) { |
| pattern = DATE_AND_TIME_PATTERN; |
| } else { |
| pattern = patternOption; |
| } |
| |
| int maximumCacheValidity = 1000; |
| DateFormat simpleFormat = null; |
| |
| try { |
| simpleFormat = new SimpleDateFormat(pattern); |
| maximumCacheValidity = CachedDateFormat.getMaximumCacheValidity(pattern); |
| } catch (IllegalArgumentException e) { |
| LogLog.warn( |
| "Could not instantiate SimpleDateFormat with pattern " |
| + patternOption, e); |
| |
| // default to the ISO8601 format |
| simpleFormat = new SimpleDateFormat(ISO8601_PATTERN); |
| } |
| |
| // if the option list contains a TZ option, then set it. |
| if ((options != null) && (options.length > 1)) { |
| TimeZone tz = TimeZone.getTimeZone((String) options[1]); |
| simpleFormat.setTimeZone(tz); |
| } else { |
| simpleFormat = new DefaultZoneDateFormat(simpleFormat); |
| } |
| |
| df = new CachedDateFormat(simpleFormat, maximumCacheValidity); |
| } |
| |
| /** |
| * Obtains an instance of pattern converter. |
| * @param options options, may be null. |
| * @return instance of pattern converter. |
| */ |
| public static DatePatternConverter newInstance( |
| final String[] options) { |
| return new DatePatternConverter(options); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void format(final LoggingEvent event, final StringBuffer output) { |
| synchronized(this) { |
| df.format(event.timeStamp, output); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public void format(final Object obj, final StringBuffer output) { |
| if (obj instanceof Date) { |
| format((Date) obj, output); |
| } |
| |
| super.format(obj, output); |
| } |
| |
| /** |
| * Append formatted date to string buffer. |
| * @param date date |
| * @param toAppendTo buffer to which formatted date is appended. |
| */ |
| public void format(final Date date, final StringBuffer toAppendTo) { |
| synchronized(this) { |
| df.format(date.getTime(), toAppendTo); |
| } |
| } |
| } |