/******************************************************************************* * This file is part of OpenNMS(R). * * Copyright (C) 2006-2011 The OpenNMS Group, Inc. * OpenNMS(R) is Copyright (C) 1999-2011 The OpenNMS Group, Inc. * * OpenNMS(R) is a registered trademark of The OpenNMS Group, Inc. * * OpenNMS(R) is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 3 of the License, * or (at your option) any later version. * * OpenNMS(R) is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with OpenNMS(R). If not, see: * http://www.gnu.org/licenses/ * * For more information contact: * OpenNMS(R) Licensing <license@opennms.org> * http://www.opennms.org/ * http://www.opennms.com/ *******************************************************************************/ package org.opennms.netmgt.syslogd; import java.text.FieldPosition; import java.text.Format; import java.text.ParseException; import java.text.ParsePosition; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Locale; import java.util.NoSuchElementException; import java.util.StringTokenizer; import java.util.TimeZone; /** * The TimestampFormat class implements the code necessary to format and parse * syslog timestamps, which come in the flavor of 'Sep 14 15:43:06'. * * @author Timothy Gerard Endres, <a href="mailto:time@ice.com">time@ice.com</a>. */ public class SyslogTimeStamp extends Format { private static final long serialVersionUID = -6116771489369028204L; /** Constant <code>DEFAULT_GMT_TZID="GMT+00"</code> */ static public final String DEFAULT_GMT_TZID = "GMT+00"; /** * <p>getInstance</p> * * @return a {@link org.opennms.netmgt.syslogd.SyslogTimeStamp} object. */ static public final SyslogTimeStamp getInstance() { return new SyslogTimeStamp(); } /** * <p>format</p> * * @param date a {@link java.util.Date} object. * @return a {@link java.lang.String} object. * @throws java.lang.IllegalArgumentException if any. */ public String format(Date date) throws IllegalArgumentException { TimeZone tz = TimeZone.getTimeZone(SyslogTimeStamp.DEFAULT_GMT_TZID); return formatTimeZone(date, tz); } /** * <p>formatTimeZone</p> * * @param date a {@link java.util.Date} object. * @param tz a {@link java.util.TimeZone} object. * @return a {@link java.lang.String} object. * @throws java.lang.IllegalArgumentException if any. */ public String formatTimeZone(Date date, TimeZone tz) throws IllegalArgumentException { SimpleDateFormat dateFormat; Locale loc = Locale.US; // UNDONE dateFormat = new SimpleDateFormat("MMM", loc); dateFormat.setTimeZone(tz); String month = dateFormat.format(date); month = month.substring(0, 3); dateFormat = new SimpleDateFormat("dd HH:mm:ss", loc); dateFormat.setTimeZone(tz); String rest = dateFormat.format(date); return month + " " + rest; } /** {@inheritDoc} */ public StringBuffer format(Object date, StringBuffer appendTo, FieldPosition fieldPos) throws IllegalArgumentException { // UNDONE - handle fieldPos! String tmpFormat = this.format((Date) date); appendTo.append(tmpFormat); return appendTo; } /** * <p>parse</p> * * @param source a {@link java.lang.String} object. * @return a {@link java.util.Date} object. * @throws java.text.ParseException if any. */ public Date parse(String source) throws ParseException { return parseTimestamp(source); } /** {@inheritDoc} */ public Object parseObject(String source, ParsePosition pos) { Date stamp = null; try { stamp = this.parseTimestamp(source); } catch (ParseException ex) { stamp = null; } return stamp; } // UNDONE - all the positions in ParseExceptions are zero. /** * <p>parseTimestamp</p> * * @param source a {@link java.lang.String} object. * @return a {@link java.util.Date} object. * @throws java.text.ParseException if any. */ public Date parseTimestamp(String source) throws ParseException { String monName = null; String dateStr = null; String hmsStr = null; String hourStr = null; String minStr = null; String secStr = null; StringTokenizer toker = new StringTokenizer(source, " "); int tokeCount = toker.countTokens(); if (tokeCount != 3) { throw new ParseException("a valid timestamp has 3 fields, not " + tokeCount, 0); } try { monName = toker.nextToken(); } catch (NoSuchElementException ex) { throw new ParseException("could not parse month name (field 1)", 0); } try { dateStr = toker.nextToken(); } catch (NoSuchElementException ex) { throw new ParseException("could not parse day of month (field 2)", 0); } try { hmsStr = toker.nextToken(); } catch (NoSuchElementException ex) { throw new ParseException("could not parse time hh:mm:ss (field 3)", 0); } toker = new StringTokenizer(hmsStr, ":"); tokeCount = toker.countTokens(); if (tokeCount != 3) { throw new ParseException("'" + hmsStr + "' is not a valid timestamp time string", 0); } try { hourStr = toker.nextToken(); } catch (NoSuchElementException ex) { throw new ParseException("could not parse time hour (field 3.1)", 0); } try { minStr = toker.nextToken(); } catch (NoSuchElementException ex) { throw new ParseException("could not parse time minute (field 3.2)", 0); } try { secStr = toker.nextToken(); } catch (NoSuchElementException ex) { throw new ParseException("could not parse time second (field 3.3)", 0); } int month = 0; int date = 0; int hour = 0; int minute = 0; int second = 0; try { month = this.monthNameToInt(monName); } catch (ParseException ex) { throw new ParseException("could not convert month name (field 1)", 0); } try { date = Integer.parseInt(dateStr); } catch (NumberFormatException ex) { throw new ParseException("could not convert month day (field 2)", 0); } if (date < 1 || date > 31) { throw new ParseException("month day '" + date + "' is out of range", 0); } try { hour = Integer.parseInt(hourStr); } catch (NumberFormatException ex) { throw new ParseException(("could not convert hour (field 3.1) '" + hourStr + "' - " + ex.getMessage()), 0); } if (hour < 0 || hour > 24) { throw new ParseException("hour '" + hour + "' is out of range", 0); } try { minute = Integer.parseInt(minStr); } catch (NumberFormatException ex) { throw new ParseException(("could not convert minute (field 3.2) '" + minStr + "' - " + ex.getMessage()), 0); } if (minute < 0 || minute > 59) { throw new ParseException("minute '" + minute + "' is out of range", 0); } try { second = Integer.parseInt(secStr); } catch (NumberFormatException ex) { throw new ParseException(("could not convert second (field 3.3) '" + secStr + "' - " + ex.getMessage()), 0); } if (second < 0 || second > 59) { throw new ParseException("second '" + second + "' is out of range", 0); } Locale loc = Locale.US; // UNDONE TimeZone tz = TimeZone.getTimeZone(SyslogTimeStamp.DEFAULT_GMT_TZID); Calendar cal = Calendar.getInstance(tz, loc); cal.setTime(new Date()); cal.set(cal.get(Calendar.YEAR), month, date, hour, minute, second); Date result = new Date(cal.getTime().getTime()); return result; } private int monthNameToInt(String name) throws ParseException { // UNDONE - this could be optimized by checking the // first character, since this resolves all // by the 'A', 'J' and 'M' months. // if (name.equalsIgnoreCase("Jan")) return 0; else if (name.equalsIgnoreCase("Feb")) return 1; else if (name.equalsIgnoreCase("Mar")) return 2; else if (name.equalsIgnoreCase("Apr")) return 3; else if (name.equalsIgnoreCase("May")) return 4; else if (name.equalsIgnoreCase("Jun")) return 5; else if (name.equalsIgnoreCase("Jul")) return 6; else if (name.equalsIgnoreCase("Aug")) return 7; else if (name.equalsIgnoreCase("Sep")) return 8; else if (name.equalsIgnoreCase("Oct")) return 9; else if (name.equalsIgnoreCase("Nov")) return 10; else if (name.equalsIgnoreCase("Dec")) return 11; throw new ParseException("unknown month name '" + name + "'", 0); } }