Java tutorial
/* * Copyright 2010 President and fellows of Harvard University. * (Author: Akio Sone) * * 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. * under the License. */ package edu.harvard.iq.safe.lockss.impl; import java.text.DateFormat; import java.text.ParseException; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.TimeZone; import java.util.concurrent.TimeUnit; import java.util.logging.Level; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.apache.commons.lang3.time.FastDateFormat; /** * * @author Akio Sone */ public class DaemonStatusDataUtil { static final Logger logger = Logger.getLogger(DaemonStatusDataUtil.class.getName()); /** * */ protected static final String sizeRegex = "^([0-9\\.]+)(TB|GB|MB|KB)$"; /** * */ protected static Pattern pss = null; /** * */ protected static final Map<String, Double> pwrTbl = new HashMap<String, Double>(); /** * */ protected static final Map<String, Long> durationUnits = new LinkedHashMap<String, Long>(); static final String IpAdRegex = "(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}" + "(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)"; static Pattern p = null; static final String FORMAT_PATTERN_FOR_HDR_TMSTMP = "dd MMM yyyy HH:mm:ss Z"; static final String FORMAT_PATTERN_FOR_LOCKSSBOX_TMSTMP = "HH:mm:ss MM/dd/yy"; static final String TIMEZONE_GMT0 = "+0000"; static { pss = Pattern.compile(sizeRegex); durationUnits.put("ms", TimeUnit.MILLISECONDS.toMillis(1)); durationUnits.put("s", TimeUnit.SECONDS.toMillis(1)); durationUnits.put("m", TimeUnit.MINUTES.toMillis(1)); durationUnits.put("h", TimeUnit.HOURS.toMillis(1)); durationUnits.put("d", TimeUnit.DAYS.toMillis(1)); durationUnits.put("w", 7L * TimeUnit.DAYS.toMillis(1)); pwrTbl.put("PB", 5D); pwrTbl.put("TB", 4D); pwrTbl.put("GB", 3D); pwrTbl.put("MB", 2D); pwrTbl.put("KB", 1D); p = Pattern.compile(IpAdRegex); } /** * * @param date * @return */ public static String getStdFrmtdTime(Date date) { return FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss zz", TimeZone.getDefault()).format(date); } public static String getStdFrmtdTime(Date date, String timezoneId) { return FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss zz", TimeZone.getTimeZone(timezoneId)).format(date); } public static String getStdFrmtdTime(Date date, String timestampPattern, String timezoneId) { return FastDateFormat.getInstance(timestampPattern, TimeZone.getTimeZone(timezoneId)).format(date); } //------------------------------------------------------------------------------ /** * * @param s * @return */ public static long auSizeConverion(String s) { String numberOnly = null; if (s.contains(",")) { numberOnly = s.replaceAll(",", ""); } else { numberOnly = s; } return Long.parseLong(numberOnly); } /** * * @param s * @return */ public static double diskUsageConverion(String s) { // 2011-05-18: After the meeting of 05-16, // the unit of this variable is set to byte rather than Mb return Math.pow(2, 20) * Double.parseDouble(s); } /** * * @param rawDaemonVersion * @return */ public static String getDaemonVersion(String rawDaemonVersion) { String daemonVersion = null; String dmnVerRegex = "Daemon\\s+(\\d+\\.\\d+\\.\\d+)\\s+built"; Pattern pdv = Pattern.compile(dmnVerRegex); Matcher m = pdv.matcher(rawDaemonVersion); if (m.find()) { logger.log(Level.FINE, "LOCKSS-daemon version found={0}", m.group(1)); daemonVersion = "" + m.group(1); } else { logger.log(Level.WARNING, "LOCKSS-daemon version is not found"); } return daemonVersion; } /** * * @param rawData * @return */ public static double getSpaceSize(String rawData) { String unit = null; String size = null; double spaceSize = 0D; String data = null; if (rawData.contains(",")) { data = rawData.replaceAll(",", ""); } else { data = rawData; } // logger.log(Level.INFO, "token="+data); Matcher m = pss.matcher(data); if (m.find()) { // logger.log(Level.INFO, "size="+m.group(1)); // logger.log(Level.INFO, "unit="+m.group(2)); size = m.group(1); unit = m.group(2); } if ((unit != null) && (size != null)) { spaceSize = Double.parseDouble(size) * Math.pow(1024D, pwrTbl.get(unit)); // logger.log(Level.INFO, "raw string("+data+")\tsize="+spaceSize +" bytes"); } return spaceSize; } /** * * @param timeStamp * @return */ /* @Deprecated public static long stringToEpocTime(String timeStamp) { long epocTime = 0L; DateFormat formater = null; if (timeStamp.equals("never") || StringUtils.isEmpty(timeStamp)) { return epocTime; } try { formater = new SimpleDateFormat("HH:mm:ss MM/dd/yy"); //logger.log(Level.INFO, "timeStamp=" + timeStamp); epocTime = ((Date) formater.parse(timeStamp)).getTime();//date.getTime(); //logger.log(Level.INFO, "AuLastCrawl in long=" + epocTime); } catch (java.text.ParseException ex) { epocTime = -1L; logger.log(Level.SEVERE, "date/time-string parsing error", ex); } catch (Exception ex) { epocTime = -1L; logger.log(Level.SEVERE, "non-parsing error", ex); } return epocTime; } */ public static long getEpocTimeFromString(String timestamp, String timezoneOffset) { long epocTime = 0L; String timestampWithTimezone = null; //FastDateFormat formater = null; if (StringUtils.isEmpty(timestamp) || timestamp.equals("never")) { return epocTime; } try { // timezoneOffset is externally given, box-wise // attach its timezone offset token (e.g., -0500) // to a timestamp to be evaluated so that it is correctly // converted at its correct timezone. if (StringUtils.isBlank(timezoneOffset)) { timestampWithTimezone = timestamp + getJVMTimezoneOffset(); logger.log(Level.WARNING, "timezoneOffset is not available: use the JVM timezone={0}", timestampWithTimezone); } else { timestampWithTimezone = timestamp + timezoneOffset; } logger.log(Level.FINEST, "After the timezone offset is attached to the timestamp={0}", timestampWithTimezone); // attach the Z format-token to // the default lockssbox timestamp pattern String formatPatternForLockssTmstmpWTz = FORMAT_PATTERN_FOR_LOCKSSBOX_TMSTMP + " Z"; epocTime = DateUtils.parseDateStrictly(timestampWithTimezone, formatPatternForLockssTmstmpWTz) .getTime(); logger.log(Level.FINEST, "epoch time={0}", epocTime); } catch (java.text.ParseException ex) { epocTime = -1L; logger.log(Level.SEVERE, "date/time-string parsing error", ex); } catch (Exception ex) { epocTime = -1L; logger.log(Level.SEVERE, "non-parsing error", ex); } return epocTime; } /** * * @param duration * @return */ public static long durationStringToMilliSeconds(String duration) { long milliSeconds = 0L; DateFormat formater = null; if (StringUtils.isEmpty(duration)) { return milliSeconds; } Map<String, Long> result = new LinkedHashMap<String, Long>(); List<String> tmps = new ArrayList<String>(); List<Long> tmpl = new ArrayList<Long>(); char[] chrs = duration.toCharArray(); //logger.log(Level.INFO, "duration token=" + duration); //out.println("chrs length=" + chrs.length); StringBuilder sba = new StringBuilder(""); StringBuilder sbd = new StringBuilder(""); boolean isLastOneNumeric = false; // frist character is always numeric for (int i = 0; i < chrs.length; i++) { //out.println(i + "th current token=" + chrs[i]); //out.println(tmps); if (((int) chrs[i] >= 48) && ((int) chrs[i] <= 57)) { // digit //out.println(i + "th current token=(" + chrs[i] + ") is a digit"); // digit if (!isLastOneNumeric) { // the last token was a unit string // save this unit string and clear the builder if (!StringUtils.isEmpty(sba.toString())) { tmps.add(sba.toString()); sba.setLength(0); } } //out.println("added to digit"); sbd.append(chrs[i]); isLastOneNumeric = true; } else { // alphabet //out.println(i + "th current token=(" + chrs[i] + ") is an alphabet"); if (isLastOneNumeric) { // hit the beginning of a new unit sba.append(chrs[i]); // save the digits that have kept so far if (i != 0) { tmpl.add(Long.parseLong(sbd.toString())); sbd.setLength(0); } } else { // the last token was a unit string, "m" of ms // save this unit string sba.append(chrs[i]); } if (i == (chrs.length - 1)) { // last element //out.println("last token"); tmps.add(sba.toString()); sba.setLength(0); } isLastOneNumeric = false; } //out.println(i + "th tmps=" + tmps); //out.println(i + "th tmpl=" + tmpl); } if (tmps.size() != tmpl.size()) { // parsing error milliSeconds = -1L; } else { for (int i = 0; i < tmps.size(); i++) { milliSeconds += durationUnits.get(tmps.get(i)) * tmpl.get(i); } //logger.log(Level.INFO, "duration in ms="+milliSeconds); } return milliSeconds; } public static boolean isOlderDaemonVersion(String underQuestion, String baseline) { LockssDaemonVersion uq = new LockssDaemonVersion(underQuestion); LockssDaemonVersion bl = new LockssDaemonVersion(baseline); return (uq.compareTo(bl) < 0); } public static String escapeHtml(String rawUrl) { String sanitizedUrl = null; logger.log(Level.FINEST, "received={0}", rawUrl); sanitizedUrl = rawUrl.replace("%", "%25"); sanitizedUrl = sanitizedUrl.replace("~", "%7E"); sanitizedUrl = sanitizedUrl.replace("|", "%7C"); sanitizedUrl = sanitizedUrl.replace("&", "%26"); logger.log(Level.FINEST, "final={0}", sanitizedUrl); return sanitizedUrl; } public static String getPeerIpAddress(String rawIp) { if (rawIp == null) { return null; } Matcher m = p.matcher(rawIp); if (m.find()) { return m.group(0); } else { return null; } } public static String calculateTimezoneOffset(String hdrTmstmpRaw, String tmstmpCurrentTime) { String timezoneOffset = null; try { // working on the timestamp taken from the http response header // usually formatted liks this "01 Mar 2012 21:12:51 GMT"; logger.log(Level.FINE, "Timestamp (timezone GMT) in Http Header={0}", hdrTmstmpRaw); // Since GMT is not recognized by DateUtils.parseDate() as GMT+0000, // replace it with +0000 String hdrTmstmp = hdrTmstmpRaw.replace("GMT", TIMEZONE_GMT0); Date hdrGMTDate = DateUtils.parseDateStrictly(hdrTmstmp, FORMAT_PATTERN_FOR_HDR_TMSTMP); long hdrMillSec = hdrGMTDate.getTime(); logger.log(Level.FINE, "timestamp in the header in UTC milliseconds={0}", hdrMillSec); // tmstmpCurrentTime, i.e., current-time timestamp taken from the // PlatformStatus page is formatted like: "16:12:51 03/01/12"; logger.log(Level.FINE, "local-time timestamp {0} by the lockss box=", tmstmpCurrentTime); // append the timezone token to the format pattern to make sure // the parser uses the GMT+0000 timezone String formatPatternForLockssTmstmpWTz = FORMAT_PATTERN_FOR_LOCKSSBOX_TMSTMP + " Z"; Date currentLocalTime = DateUtils.parseDate(tmstmpCurrentTime + " " + TIMEZONE_GMT0, formatPatternForLockssTmstmpWTz); Long currentLocalTimeMillSec = currentLocalTime.getTime(); logger.log(Level.FINE, "Resulting time in UTC milliseconds={0}", currentLocalTimeMillSec); // take the difference betwen header and curret-time timestamp Long offsetToGMTMillSec = currentLocalTimeMillSec - hdrMillSec; logger.log(Level.FINE, "diff in millis={0}", offsetToGMTMillSec); Long offsetToGMTmin = TimeUnit.MILLISECONDS.toMinutes(offsetToGMTMillSec); logger.log(Level.FINE, "offset To GMT in min={0}", offsetToGMTmin); Long hPart = 0L; Long mPart = 0L; // remove the sign from the min part to avoid a case like -04-30 mPart = Math.abs(offsetToGMTmin % 60L); hPart = offsetToGMTmin / 60L; timezoneOffset = getUTCOffsetString(hPart, mPart); logger.log(Level.FINE, "timezone offset to be used for this lockss box={0}", timezoneOffset); } catch (ParseException ex) { logger.log(Level.SEVERE, "failed to parse the givne timestamp", ex); } finally { if (StringUtils.isBlank(timezoneOffset)) { timezoneOffset = getJVMTimezoneOffset(); } } return timezoneOffset; } public static String getUTCOffsetString(long hour, long min) { long lhour = hour; if (Math.abs(hour) >= 0 && Math.abs(hour) <= 23) { // within the normal range // do nothing } else if (Math.abs(hour) == 24) { lhour = 0L; } else { // set to 0 lhour = 0L; } long lmin = Math.abs(min); if (lmin >= 0 && lmin <= 59) { // within the normal range // however, there might be some second-level difference between // the header time and the lockss-page rendering one // such as -4:59 instead of -05:00 if (lmin <= 2) { // set back to zero // no hour change lmin = 0L; } else if (lmin >= 28L && lmin <= 32L) { // min set to 30; no hour change lmin = 30L; } else if (lmin >= 58) { // hour +1, min set to 0 lmin = 0L; if (lhour < 0) { lhour--; } else { lhour++; } } } else { // out-of-the normal range // set to 0 lmin = 0L; } logger.log(Level.FINEST, "hour={0}=>lhour{1}", new Object[] { hour, lhour }); logger.log(Level.FINEST, " min={0}=>lmin={1}", new Object[] { min, lmin }); return String.format(" %+03d%02d", lhour, lmin); } public static String getJVMTimezoneOffset() { String jvmTzOffset = null; Long jvmOffsetMins = TimeUnit.MILLISECONDS.toMinutes(TimeZone.getDefault().getRawOffset()); logger.log(Level.FINE, "This JVM's timezone offset in min={0}", jvmOffsetMins); Long jvmHourPart = jvmOffsetMins / 60L; // remove the sign from the min part to avoid a case like -04-30 Long jvmMinPart = Math.abs(jvmOffsetMins % 60L); logger.log(Level.FINE, "jvmHourPart={0}", jvmHourPart); logger.log(Level.FINE, "jvmMinPart={0}", jvmMinPart); jvmTzOffset = getUTCOffsetString(jvmHourPart, jvmMinPart); if (StringUtils.isBlank(jvmTzOffset)) { logger.log(Level.WARNING, "JVM's timezone is NOT available: using the GMT+0000"); jvmTzOffset = TIMEZONE_GMT0; } logger.log(Level.FINE, "This JVM's timezone offset={0}", jvmTzOffset); return jvmTzOffset; } }