1 // Copyright (c) 2004-2009 Brian Wellington (bwelling (at) xbill.org) 2 3 package org.xbill.DNS; 4 5 /** 6 * Routines for deal with the lists of types found in NSEC/NSEC3 records. 7 * 8 * @author Brian Wellington 9 */ 10 11 import java.io.*; 12 import java.util.*; 13 14 final class TypeBitmap implements Serializable { 15 16 private static final long serialVersionUID = -125354057735389003L; 17 18 private TreeSet types; 19 20 private 21 TypeBitmap() { 22 types = new TreeSet(); 23 } 24 25 public 26 TypeBitmap(int [] array) { 27 this(); 28 for (int i = 0; i < array.length; i++) { 29 Type.check(array[i]); 30 types.add(new Integer(array[i])); 31 } 32 } 33 34 public 35 TypeBitmap(DNSInput in) throws WireParseException { 36 this(); 37 int lastbase = -1; 38 while (in.remaining() > 0) { 39 if (in.remaining() < 2) 40 throw new WireParseException 41 ("invalid bitmap descriptor"); 42 int mapbase = in.readU8(); 43 if (mapbase < lastbase) 44 throw new WireParseException("invalid ordering"); 45 int maplength = in.readU8(); 46 if (maplength > in.remaining()) 47 throw new WireParseException("invalid bitmap"); 48 for (int i = 0; i < maplength; i++) { 49 int current = in.readU8(); 50 if (current == 0) 51 continue; 52 for (int j = 0; j < 8; j++) { 53 if ((current & (1 << (7 - j))) == 0) 54 continue; 55 int typecode = mapbase * 256 + + i * 8 + j; 56 types.add(Mnemonic.toInteger(typecode)); 57 } 58 } 59 } 60 } 61 62 public 63 TypeBitmap(Tokenizer st) throws IOException { 64 this(); 65 while (true) { 66 Tokenizer.Token t = st.get(); 67 if (!t.isString()) 68 break; 69 int typecode = Type.value(t.value); 70 if (typecode < 0) { 71 throw st.exception("Invalid type: " + t.value); 72 } 73 types.add(Mnemonic.toInteger(typecode)); 74 } 75 st.unget(); 76 } 77 78 public int [] 79 toArray() { 80 int [] array = new int[types.size()]; 81 int n = 0; 82 for (Iterator it = types.iterator(); it.hasNext(); ) 83 array[n++] = ((Integer)it.next()).intValue(); 84 return array; 85 } 86 87 public String 88 toString() { 89 StringBuffer sb = new StringBuffer(); 90 for (Iterator it = types.iterator(); it.hasNext(); ) { 91 int t = ((Integer)it.next()).intValue(); 92 sb.append(Type.string(t)); 93 if (it.hasNext()) 94 sb.append(' '); 95 } 96 return sb.toString(); 97 } 98 99 private static void 100 mapToWire(DNSOutput out, TreeSet map, int mapbase) { 101 int arraymax = (((Integer)map.last()).intValue()) & 0xFF; 102 int arraylength = (arraymax / 8) + 1; 103 int [] array = new int[arraylength]; 104 out.writeU8(mapbase); 105 out.writeU8(arraylength); 106 for (Iterator it = map.iterator(); it.hasNext(); ) { 107 int typecode = ((Integer)it.next()).intValue(); 108 array[(typecode & 0xFF) / 8] |= (1 << ( 7 - typecode % 8)); 109 } 110 for (int j = 0; j < arraylength; j++) 111 out.writeU8(array[j]); 112 } 113 114 public void 115 toWire(DNSOutput out) { 116 if (types.size() == 0) 117 return; 118 119 int mapbase = -1; 120 TreeSet map = new TreeSet(); 121 122 for (Iterator it = types.iterator(); it.hasNext(); ) { 123 int t = ((Integer)it.next()).intValue(); 124 int base = t >> 8; 125 if (base != mapbase) { 126 if (map.size() > 0) { 127 mapToWire(out, map, mapbase); 128 map.clear(); 129 } 130 mapbase = base; 131 } 132 map.add(new Integer(t)); 133 } 134 mapToWire(out, map, mapbase); 135 } 136 137 public boolean 138 empty() { 139 return types.isEmpty(); 140 } 141 142 public boolean 143 contains(int typecode) { 144 return types.contains(Mnemonic.toInteger(typecode)); 145 } 146 147 } 148