1 // Copyright (c) 1999-2004 Brian Wellington (bwelling (at) xbill.org) 2 3 package org.xbill.DNS; 4 5 /** 6 * Routines for parsing BIND-style TTL values. These values consist of 7 * numbers followed by 1 letter units of time (W - week, D - day, H - hour, 8 * M - minute, S - second). 9 * 10 * @author Brian Wellington 11 */ 12 13 public final class TTL { 14 15 public static final long MAX_VALUE = 0x7FFFFFFFL; 16 17 private 18 TTL() {} 19 20 static void 21 check(long i) { 22 if (i < 0 || i > MAX_VALUE) 23 throw new InvalidTTLException(i); 24 } 25 26 /** 27 * Parses a TTL-like value, which can either be expressed as a number or a 28 * BIND-style string with numbers and units. 29 * @param s The string representing the numeric value. 30 * @param clamp Whether to clamp values in the range [MAX_VALUE + 1, 2^32 -1] 31 * to MAX_VALUE. This should be donw for TTLs, but not other values which 32 * can be expressed in this format. 33 * @return The value as a number of seconds 34 * @throws NumberFormatException The string was not in a valid TTL format. 35 */ 36 public static long 37 parse(String s, boolean clamp) { 38 if (s == null || s.length() == 0 || !Character.isDigit(s.charAt(0))) 39 throw new NumberFormatException(); 40 long value = 0; 41 long ttl = 0; 42 for (int i = 0; i < s.length(); i++) { 43 char c = s.charAt(i); 44 long oldvalue = value; 45 if (Character.isDigit(c)) { 46 value = (value * 10) + Character.getNumericValue(c); 47 if (value < oldvalue) 48 throw new NumberFormatException(); 49 } else { 50 switch (Character.toUpperCase(c)) { 51 case 'W': value *= 7; 52 case 'D': value *= 24; 53 case 'H': value *= 60; 54 case 'M': value *= 60; 55 case 'S': break; 56 default: throw new NumberFormatException(); 57 } 58 ttl += value; 59 value = 0; 60 if (ttl > 0xFFFFFFFFL) 61 throw new NumberFormatException(); 62 } 63 } 64 if (ttl == 0) 65 ttl = value; 66 67 if (ttl > 0xFFFFFFFFL) 68 throw new NumberFormatException(); 69 else if (ttl > MAX_VALUE && clamp) 70 ttl = MAX_VALUE; 71 return ttl; 72 } 73 74 /** 75 * Parses a TTL, which can either be expressed as a number or a BIND-style 76 * string with numbers and units. 77 * @param s The string representing the TTL 78 * @return The TTL as a number of seconds 79 * @throws NumberFormatException The string was not in a valid TTL format. 80 */ 81 public static long 82 parseTTL(String s) { 83 return parse(s, true); 84 } 85 86 public static String 87 format(long ttl) { 88 TTL.check(ttl); 89 StringBuffer sb = new StringBuffer(); 90 long secs, mins, hours, days, weeks; 91 secs = ttl % 60; 92 ttl /= 60; 93 mins = ttl % 60; 94 ttl /= 60; 95 hours = ttl % 24; 96 ttl /= 24; 97 days = ttl % 7; 98 ttl /= 7; 99 weeks = ttl; 100 if (weeks > 0) 101 sb.append(weeks + "W"); 102 if (days > 0) 103 sb.append(days + "D"); 104 if (hours > 0) 105 sb.append(hours + "H"); 106 if (mins > 0) 107 sb.append(mins + "M"); 108 if (secs > 0 || (weeks == 0 && days == 0 && hours == 0 && mins == 0)) 109 sb.append(secs + "S"); 110 return sb.toString(); 111 } 112 113 } 114