1 // Copyright (c) 2003-2004 Brian Wellington (bwelling (at) xbill.org) 2 3 package org.xbill.DNS; 4 5 import java.io.*; 6 import java.util.*; 7 8 /** 9 * A helper class for constructing dynamic DNS (DDNS) update messages. 10 * 11 * @author Brian Wellington 12 */ 13 14 public class Update extends Message { 15 16 private Name origin; 17 private int dclass; 18 19 /** 20 * Creates an update message. 21 * @param zone The name of the zone being updated. 22 * @param dclass The class of the zone being updated. 23 */ 24 public 25 Update(Name zone, int dclass) { 26 super(); 27 if (!zone.isAbsolute()) 28 throw new RelativeNameException(zone); 29 DClass.check(dclass); 30 getHeader().setOpcode(Opcode.UPDATE); 31 Record soa = Record.newRecord(zone, Type.SOA, DClass.IN); 32 addRecord(soa, Section.QUESTION); 33 this.origin = zone; 34 this.dclass = dclass; 35 } 36 37 /** 38 * Creates an update message. The class is assumed to be IN. 39 * @param zone The name of the zone being updated. 40 */ 41 public 42 Update(Name zone) { 43 this(zone, DClass.IN); 44 } 45 46 private void 47 newPrereq(Record rec) { 48 addRecord(rec, Section.PREREQ); 49 } 50 51 private void 52 newUpdate(Record rec) { 53 addRecord(rec, Section.UPDATE); 54 } 55 56 /** 57 * Inserts a prerequisite that the specified name exists; that is, there 58 * exist records with the given name in the zone. 59 */ 60 public void 61 present(Name name) { 62 newPrereq(Record.newRecord(name, Type.ANY, DClass.ANY, 0)); 63 } 64 65 /** 66 * Inserts a prerequisite that the specified rrset exists; that is, there 67 * exist records with the given name and type in the zone. 68 */ 69 public void 70 present(Name name, int type) { 71 newPrereq(Record.newRecord(name, type, DClass.ANY, 0)); 72 } 73 74 /** 75 * Parses a record from the string, and inserts a prerequisite that the 76 * record exists. Due to the way value-dependent prequisites work, the 77 * condition that must be met is that the set of all records with the same 78 * and type in the update message must be identical to the set of all records 79 * with that name and type on the server. 80 * @throws IOException The record could not be parsed. 81 */ 82 public void 83 present(Name name, int type, String record) throws IOException { 84 newPrereq(Record.fromString(name, type, dclass, 0, record, origin)); 85 } 86 87 /** 88 * Parses a record from the tokenizer, and inserts a prerequisite that the 89 * record exists. Due to the way value-dependent prequisites work, the 90 * condition that must be met is that the set of all records with the same 91 * and type in the update message must be identical to the set of all records 92 * with that name and type on the server. 93 * @throws IOException The record could not be parsed. 94 */ 95 public void 96 present(Name name, int type, Tokenizer tokenizer) throws IOException { 97 newPrereq(Record.fromString(name, type, dclass, 0, tokenizer, origin)); 98 } 99 100 /** 101 * Inserts a prerequisite that the specified record exists. Due to the way 102 * value-dependent prequisites work, the condition that must be met is that 103 * the set of all records with the same and type in the update message must 104 * be identical to the set of all records with that name and type on the server. 105 */ 106 public void 107 present(Record record) { 108 newPrereq(record); 109 } 110 111 /** 112 * Inserts a prerequisite that the specified name does not exist; that is, 113 * there are no records with the given name in the zone. 114 */ 115 public void 116 absent(Name name) { 117 newPrereq(Record.newRecord(name, Type.ANY, DClass.NONE, 0)); 118 } 119 120 /** 121 * Inserts a prerequisite that the specified rrset does not exist; that is, 122 * there are no records with the given name and type in the zone. 123 */ 124 public void 125 absent(Name name, int type) { 126 newPrereq(Record.newRecord(name, type, DClass.NONE, 0)); 127 } 128 129 /** 130 * Parses a record from the string, and indicates that the record 131 * should be inserted into the zone. 132 * @throws IOException The record could not be parsed. 133 */ 134 public void 135 add(Name name, int type, long ttl, String record) throws IOException { 136 newUpdate(Record.fromString(name, type, dclass, ttl, record, origin)); 137 } 138 139 /** 140 * Parses a record from the tokenizer, and indicates that the record 141 * should be inserted into the zone. 142 * @throws IOException The record could not be parsed. 143 */ 144 public void 145 add(Name name, int type, long ttl, Tokenizer tokenizer) throws IOException { 146 newUpdate(Record.fromString(name, type, dclass, ttl, tokenizer, 147 origin)); 148 } 149 150 /** 151 * Indicates that the record should be inserted into the zone. 152 */ 153 public void 154 add(Record record) { 155 newUpdate(record); 156 } 157 158 /** 159 * Indicates that the records should be inserted into the zone. 160 */ 161 public void 162 add(Record [] records) { 163 for (int i = 0; i < records.length; i++) 164 add(records[i]); 165 } 166 167 /** 168 * Indicates that all of the records in the rrset should be inserted into the 169 * zone. 170 */ 171 public void 172 add(RRset rrset) { 173 for (Iterator it = rrset.rrs(); it.hasNext(); ) 174 add((Record) it.next()); 175 } 176 177 /** 178 * Indicates that all records with the given name should be deleted from 179 * the zone. 180 */ 181 public void 182 delete(Name name) { 183 newUpdate(Record.newRecord(name, Type.ANY, DClass.ANY, 0)); 184 } 185 186 /** 187 * Indicates that all records with the given name and type should be deleted 188 * from the zone. 189 */ 190 public void 191 delete(Name name, int type) { 192 newUpdate(Record.newRecord(name, type, DClass.ANY, 0)); 193 } 194 195 /** 196 * Parses a record from the string, and indicates that the record 197 * should be deleted from the zone. 198 * @throws IOException The record could not be parsed. 199 */ 200 public void 201 delete(Name name, int type, String record) throws IOException { 202 newUpdate(Record.fromString(name, type, DClass.NONE, 0, record, 203 origin)); 204 } 205 206 /** 207 * Parses a record from the tokenizer, and indicates that the record 208 * should be deleted from the zone. 209 * @throws IOException The record could not be parsed. 210 */ 211 public void 212 delete(Name name, int type, Tokenizer tokenizer) throws IOException { 213 newUpdate(Record.fromString(name, type, DClass.NONE, 0, tokenizer, 214 origin)); 215 } 216 217 /** 218 * Indicates that the specified record should be deleted from the zone. 219 */ 220 public void 221 delete(Record record) { 222 newUpdate(record.withDClass(DClass.NONE, 0)); 223 } 224 225 /** 226 * Indicates that the records should be deleted from the zone. 227 */ 228 public void 229 delete(Record [] records) { 230 for (int i = 0; i < records.length; i++) 231 delete(records[i]); 232 } 233 234 /** 235 * Indicates that all of the records in the rrset should be deleted from the 236 * zone. 237 */ 238 public void 239 delete(RRset rrset) { 240 for (Iterator it = rrset.rrs(); it.hasNext(); ) 241 delete((Record) it.next()); 242 } 243 244 /** 245 * Parses a record from the string, and indicates that the record 246 * should be inserted into the zone replacing any other records with the 247 * same name and type. 248 * @throws IOException The record could not be parsed. 249 */ 250 public void 251 replace(Name name, int type, long ttl, String record) throws IOException { 252 delete(name, type); 253 add(name, type, ttl, record); 254 } 255 256 /** 257 * Parses a record from the tokenizer, and indicates that the record 258 * should be inserted into the zone replacing any other records with the 259 * same name and type. 260 * @throws IOException The record could not be parsed. 261 */ 262 public void 263 replace(Name name, int type, long ttl, Tokenizer tokenizer) throws IOException 264 { 265 delete(name, type); 266 add(name, type, ttl, tokenizer); 267 } 268 269 /** 270 * Indicates that the record should be inserted into the zone replacing any 271 * other records with the same name and type. 272 */ 273 public void 274 replace(Record record) { 275 delete(record.getName(), record.getType()); 276 add(record); 277 } 278 279 /** 280 * Indicates that the records should be inserted into the zone replacing any 281 * other records with the same name and type as each one. 282 */ 283 public void 284 replace(Record [] records) { 285 for (int i = 0; i < records.length; i++) 286 replace(records[i]); 287 } 288 289 /** 290 * Indicates that all of the records in the rrset should be inserted into the 291 * zone replacing any other records with the same name and type. 292 */ 293 public void 294 replace(RRset rrset) { 295 delete(rrset.getName(), rrset.getType()); 296 for (Iterator it = rrset.rrs(); it.hasNext(); ) 297 add((Record) it.next()); 298 } 299 300 } 301