1 // Copyright (c) 2003-2004 Brian Wellington (bwelling@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
Update(Name zone, int dclass)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
Update(Name zone)42 Update(Name zone) {
43 	this(zone, DClass.IN);
44 }
45 
46 private void
newPrereq(Record rec)47 newPrereq(Record rec) {
48 	addRecord(rec, Section.PREREQ);
49 }
50 
51 private void
newUpdate(Record rec)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
present(Name name)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
present(Name name, int type)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
present(Name name, int type, String record)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
present(Name name, int type, Tokenizer tokenizer)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
present(Record record)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
absent(Name name)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
absent(Name name, int type)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
add(Name name, int type, long ttl, String record)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
add(Name name, int type, long ttl, Tokenizer tokenizer)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
add(Record record)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
add(Record [] records)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
add(RRset rrset)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
delete(Name name)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
delete(Name name, int type)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
delete(Name name, int type, String record)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
delete(Name name, int type, Tokenizer tokenizer)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
delete(Record record)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
delete(Record [] records)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
delete(RRset rrset)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
replace(Name name, int type, long ttl, String record)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
replace(Name name, int type, long ttl, Tokenizer tokenizer)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
replace(Record record)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
replace(Record [] records)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
replace(RRset rrset)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