| // 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(); |
| } |
| |
| } |