// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org) package org.xbill.DNS; /** * Routines for parsing BIND-style TTL values. These values consist of * numbers followed by 1 letter units of time (W - week, D - day, H - hour, * M - minute, S - second). * * @author Brian Wellington */ public final class TTL { public static final long MAX_VALUE = 0x7FFFFFFFL; private TTL() {} static void check(long i) { if (i < 0 || i > MAX_VALUE) throw new InvalidTTLException(i); } /** * Parses a TTL-like value, which can either be expressed as a number or a * BIND-style string with numbers and units. * @param s The string representing the numeric value. * @param clamp Whether to clamp values in the range [MAX_VALUE + 1, 2^32 -1] * to MAX_VALUE. This should be donw for TTLs, but not other values which * can be expressed in this format. * @return The value as a number of seconds * @throws NumberFormatException The string was not in a valid TTL format. */ public static long parse(String s, boolean clamp) { if (s == null || s.length() == 0 || !Character.isDigit(s.charAt(0))) throw new NumberFormatException(); long value = 0; long ttl = 0; for (int i = 0; i < s.length(); i++) { char c = s.charAt(i); long oldvalue = value; if (Character.isDigit(c)) { value = (value * 10) + Character.getNumericValue(c); if (value < oldvalue) throw new NumberFormatException(); } else { switch (Character.toUpperCase(c)) { case 'W': value *= 7; case 'D': value *= 24; case 'H': value *= 60; case 'M': value *= 60; case 'S': break; default: throw new NumberFormatException(); } ttl += value; value = 0; if (ttl > 0xFFFFFFFFL) throw new NumberFormatException(); } } if (ttl == 0) ttl = value; if (ttl > 0xFFFFFFFFL) throw new NumberFormatException(); else if (ttl > MAX_VALUE && clamp) ttl = MAX_VALUE; return ttl; } /** * Parses a TTL, which can either be expressed as a number or a BIND-style * string with numbers and units. * @param s The string representing the TTL * @return The TTL as a number of seconds * @throws NumberFormatException The string was not in a valid TTL format. */ public static long parseTTL(String s) { return parse(s, true); } public static String format(long ttl) { TTL.check(ttl); StringBuffer sb = new StringBuffer(); long secs, mins, hours, days, weeks; secs = ttl % 60; ttl /= 60; mins = ttl % 60; ttl /= 60; hours = ttl % 24; ttl /= 24; days = ttl % 7; ttl /= 7; weeks = ttl; if (weeks > 0) sb.append(weeks + "W"); if (days > 0) sb.append(days + "D"); if (hours > 0) sb.append(hours + "H"); if (mins > 0) sb.append(mins + "M"); if (secs > 0 || (weeks == 0 && days == 0 && hours == 0 && mins == 0)) sb.append(secs + "S"); return sb.toString(); } }