001: // Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
002:
003: package org.xbill.DNS;
004:
005: /**
006: * Routines for parsing BIND-style TTL values. These values consist of
007: * numbers followed by 1 letter units of time (W - week, D - day, H - hour,
008: * M - minute, S - second).
009: *
010: * @author Brian Wellington
011: */
012:
013: public final class TTL {
014:
015: public static final long MAX_VALUE = 0x7FFFFFFFL;
016:
017: private TTL() {
018: }
019:
020: static void check(long i) {
021: if (i < 0 || i > MAX_VALUE)
022: throw new InvalidTTLException(i);
023: }
024:
025: /**
026: * Parses a TTL-like value, which can either be expressed as a number or a
027: * BIND-style string with numbers and units.
028: * @param s The string representing the numeric value.
029: * @param clamp Whether to clamp values in the range [MAX_VALUE + 1, 2^32 -1]
030: * to MAX_VALUE. This should be donw for TTLs, but not other values which
031: * can be expressed in this format.
032: * @return The value as a number of seconds
033: * @throws NumberFormatException The string was not in a valid TTL format.
034: */
035: public static long parse(String s, boolean clamp) {
036: if (s == null || s.length() == 0
037: || !Character.isDigit(s.charAt(0)))
038: throw new NumberFormatException();
039: long value = 0;
040: long ttl = 0;
041: for (int i = 0; i < s.length(); i++) {
042: char c = s.charAt(i);
043: long oldvalue = value;
044: if (Character.isDigit(c)) {
045: value = (value * 10) + Character.getNumericValue(c);
046: if (value < oldvalue)
047: throw new NumberFormatException();
048: } else {
049: switch (Character.toUpperCase(c)) {
050: case 'W':
051: value *= 7;
052: case 'D':
053: value *= 24;
054: case 'H':
055: value *= 60;
056: case 'M':
057: value *= 60;
058: case 'S':
059: break;
060: default:
061: throw new NumberFormatException();
062: }
063: ttl += value;
064: value = 0;
065: if (ttl > 0xFFFFFFFFL)
066: throw new NumberFormatException();
067: }
068: }
069: if (ttl == 0)
070: ttl = value;
071:
072: if (ttl > 0xFFFFFFFFL)
073: throw new NumberFormatException();
074: else if (ttl > MAX_VALUE && clamp)
075: ttl = MAX_VALUE;
076: return ttl;
077: }
078:
079: /**
080: * Parses a TTL, which can either be expressed as a number or a BIND-style
081: * string with numbers and units.
082: * @param s The string representing the TTL
083: * @return The TTL as a number of seconds
084: * @throws NumberFormatException The string was not in a valid TTL format.
085: */
086: public static long parseTTL(String s) {
087: return parse(s, true);
088: }
089:
090: public static String format(long ttl) {
091: TTL.check(ttl);
092: StringBuffer sb = new StringBuffer();
093: long secs, mins, hours, days, weeks;
094: secs = ttl % 60;
095: ttl /= 60;
096: mins = ttl % 60;
097: ttl /= 60;
098: hours = ttl % 24;
099: ttl /= 24;
100: days = ttl % 7;
101: ttl /= 7;
102: weeks = ttl;
103: if (weeks > 0)
104: sb.append(weeks + "W");
105: if (days > 0)
106: sb.append(days + "D");
107: if (hours > 0)
108: sb.append(hours + "H");
109: if (mins > 0)
110: sb.append(mins + "M");
111: if (secs > 0
112: || (weeks == 0 && days == 0 && hours == 0 && mins == 0))
113: sb.append(secs + "S");
114: return sb.toString();
115: }
116:
117: }
|