/*
* 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.synapse.transport.http.access;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.TimeZone;
/**
* Utility methods related to the Access Time
*/
public class AccessTimeUtil {
private static String calculateTimeZoneOffset(long offset) {
StringBuilder tz = new StringBuilder();
if ((offset < 0)) {
tz.append("-");
offset = -offset;
} else {
tz.append("+");
}
long hourOffset = offset / (1000 * 60 * 60);
long minuteOffset = (offset / (1000 * 60)) % 60;
if (hourOffset < 10) {
tz.append("0");
}
tz.append(hourOffset);
if (minuteOffset < 10) {
tz.append("0");
}
tz.append(minuteOffset);
return tz.toString();
}
/**
* gets the timezone +/-{****}}, offset from GMT,
* @return String time zone (eg, +0530, -0600).
*/
public static String getTimeZone() {
try {
int offset = TimeZone.getDefault().getRawOffset();
return calculateTimeZoneOffset(offset);
} catch (Exception e) {
return "";
}
}
/**
* AccessDateStruct Class
*/
private static class AccessDateStruct {
private Date currentDate = new Date();
private String currentDateString = null;
private SimpleDateFormat dayFormatter = new SimpleDateFormat("dd");
private SimpleDateFormat monthFormatter = new SimpleDateFormat("MM");
private SimpleDateFormat yearFormatter = new SimpleDateFormat("yyyy");
private SimpleDateFormat timeFormatter = new SimpleDateFormat("HH:mm:ss");
public AccessDateStruct() {
TimeZone tz = TimeZone.getDefault();
dayFormatter.setTimeZone(tz);
monthFormatter.setTimeZone(tz);
yearFormatter.setTimeZone(tz);
timeFormatter.setTimeZone(tz);
}
}
/**
* The system time when we last updated the Date, that is used for log lines.
*/
private static final ThreadLocal<AccessDateStruct> currentDateStruct =
new ThreadLocal<AccessDateStruct>() {
@Override
protected AccessDateStruct initialValue() {
return new AccessDateStruct();
}
};
/**
* This method returns a Date object that is accurate to within one second.
* If a thread calls this method to get a Date and it's been less than 1
* second since a new Date was created, this method simply gives out the
* same Date again so that the system doesn't spend time creating Date
* objects unnecessarily.
*
* @return Date
*/
public static Date getDate() {
// Only create a new Date once per second, max.
long systime = System.currentTimeMillis();
AccessDateStruct struct = currentDateStruct.get();
if ((systime - struct.currentDate.getTime()) > 1000) {
struct.currentDate.setTime(systime);
struct.currentDateString = null;
}
return struct.currentDate;
}
private static AccessDateStruct getAccessDateStruct(Date date) {
AccessDateStruct struct = currentDateStruct.get();
if (struct.currentDateString == null) {
StringBuilder current = new StringBuilder(32);
current.append('[');
current.append(struct.dayFormatter.format(date));
current.append('/');
current.append(lookup(struct.monthFormatter.format(date)));
current.append('/');
current.append(struct.yearFormatter.format(date));
current.append(':');
current.append(struct.timeFormatter.format(date));
current.append(' ');
current.append(AccessTimeUtil.getTimeZone());
current.append(']');
struct.currentDateString = current.toString();
}
return struct;
}
/**
* Return the month abbreviation for the specified month, which must
* be a two-digit String.
*
* @param month Month number ("01" .. "12").
* @return - the month
*/
private static String lookup(String month) {
int index;
try {
index = Integer.parseInt(month) - 1;
} catch (Throwable t) {
handleThrowable(t);
index = 0; // Can not happen, in theory
}
return (AccessConstants.MONTHS[index]);
}
public static String getAccessDate(Date date) {
return getAccessDateFormatted(date);
}
/**
* Checks whether the supplied Throwable is one that needs to be
* re-thrown and swallows all others.
*
* @param t the Throwable to check
*/
public static void handleThrowable(Throwable t) {
if (t instanceof ThreadDeath) {
throw (ThreadDeath) t;
}
if (t instanceof VirtualMachineError) {
throw (VirtualMachineError) t;
}
// All other instances of Throwable will be silently swallowed
}
/**
* Format the time
* @param date
* @return
*/
private static String getAccessDateFormatted(Date date) {
AccessDateStruct struct = currentDateStruct.get();
StringBuilder current = new StringBuilder(32);
current.append('[');
current.append(struct.dayFormatter.format(date));
current.append('/');
current.append(lookup(struct.monthFormatter.format(date)));
current.append('/');
current.append(struct.yearFormatter.format(date));
current.append(':');
current.append(struct.timeFormatter.format(date));
current.append(' ');
current.append(AccessTimeUtil.getTimeZone());
current.append(']');
return current.toString();
}
}