Home | History | Annotate | Download | only in DNS
      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