com.blackberry.logdriver.timestamp.Rfc5424TimestampParser.java Source code

Java tutorial

Introduction

Here is the source code for com.blackberry.logdriver.timestamp.Rfc5424TimestampParser.java

Source

/** Copyright (c) 2014 BlackBerry Limited
 *
 *  Licensed 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 com.blackberry.logdriver.timestamp;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.TimeZone;

import org.apache.commons.lang.time.FastDateFormat;

public class Rfc5424TimestampParser implements TimestampParser {
    private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
    private final FastDateFormat dateFormatWriter = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");

    private static final class SizeLimitedLinkedHashMap<K, V> extends LinkedHashMap<K, V> {
        private static final long serialVersionUID = 1L;
        private static final int MAX_ENTRIES = 120;

        @Override
        protected boolean removeEldestEntry(Map.Entry<K, V> eldest) {
            return size() > MAX_ENTRIES;
        }
    }

    private final Map<String, Long> dateCache = new SizeLimitedLinkedHashMap<String, Long>();
    private final boolean daylightSavings;
    private final TimeZone tz;
    private final long tzOffset;

    public Rfc5424TimestampParser() {
        tz = Calendar.getInstance().getTimeZone();
        tzOffset = tz.getRawOffset();
        daylightSavings = tz.useDaylightTime();
    }

    @Override
    public String[] splitLine(String line) {
        String[] split = line.split(" ", 2);
        if (split.length == 1) {
            return new String[] { null, line };
        } else {
            return split;
        }
    }

    @Override
    public long parseTimestatmp(String timestamp) throws ParseException {
        try {
            // Parse the easy part of the string
            String firstPart = timestamp.substring(0, 19);
            Long time;
            time = dateCache.get(firstPart);
            if (time == null) {
                time = dateFormat.parse(firstPart).getTime();
                dateCache.put(firstPart, time);
            }
            int currentIndex = 19;
            char c = timestamp.charAt(currentIndex);

            // Check for fractional seconds to add. We only record up to millisecond
            // precision, so only grab up to three digits.
            if (timestamp.charAt(currentIndex) == '.') {
                // There are fractional seconds, so grab up to 3.
                // The first digit is guaranteed by the spec. After that, we need to
                // check if we still have digits.
                // The spec requires a timezone, so we can't run out of digits
                // before we run out of string.
                currentIndex++;
                c = timestamp.charAt(currentIndex);
                time += 100 * Character.getNumericValue(c);
                currentIndex++;
                c = timestamp.charAt(currentIndex);
                if (Character.isDigit(c)) {
                    time += 10 * Character.getNumericValue(c);
                    currentIndex++;
                    c = timestamp.charAt(currentIndex);
                    if (Character.isDigit(c)) {
                        time += Character.getNumericValue(c);
                        currentIndex++;
                        c = timestamp.charAt(currentIndex);
                        // Now just go through the digits until we're done.
                        while (Character.isDigit(c)) {
                            currentIndex++;
                            c = timestamp.charAt(currentIndex);
                        }
                    }
                }

            }

            // Now adjust for timezone offset. either Z or +/-00:00
            boolean positiveTimeZone = true;
            if (c == 'Z') {
                // That's fine. No adjustment.
            } else {
                if (c == '+') {
                    positiveTimeZone = true;
                } else if (c == '-') {
                    positiveTimeZone = false;
                } else {
                    throw new IllegalArgumentException("Malformed date:" + timestamp);
                }

                // Grab the next 2 for hour. Then skip the colon and grab the next
                // 2.
                currentIndex++;
                int hour = Integer.parseInt(timestamp.substring(currentIndex, currentIndex + 2));
                currentIndex += 2;
                c = timestamp.charAt(currentIndex);
                if (c != ':') {
                    throw new IllegalArgumentException("Malformed date:" + timestamp);
                }
                currentIndex++;
                int minute = Integer.parseInt(timestamp.substring(currentIndex, currentIndex + 2));

                int offset = (60 * hour + minute) * 60 * 1000;
                if (positiveTimeZone) {
                    time -= offset;
                } else {
                    time += offset;
                }

            }

            // If we support daylight savings, then we need to keep checking if we're
            // in
            // daylight savings or not.
            if (daylightSavings) {
                time += tz.getOffset(time);
            } else {
                time += tzOffset;
            }

            return time;
        } catch (ParseException e) {
            throw e;
        } catch (Throwable t) {
            ParseException e = new ParseException("Unexpected Exception", 0);
            e.initCause(t);
            throw e;
        }
    }

    @Override
    public String timestampToString(long timestamp) {
        return dateFormatWriter.format(timestamp);
    }
}