1// Copyright (c) 2003-2004 Brian Wellington (bwelling@xbill.org)
2
3package org.xbill.DNS;
4
5import java.io.*;
6import java.util.*;
7
8/**
9 * A helper class for constructing dynamic DNS (DDNS) update messages.
10 *
11 * @author Brian Wellington
12 */
13
14public class Update extends Message {
15
16private Name origin;
17private 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 */
24public
25Update(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 */
41public
42Update(Name zone) {
43	this(zone, DClass.IN);
44}
45
46private void
47newPrereq(Record rec) {
48	addRecord(rec, Section.PREREQ);
49}
50
51private void
52newUpdate(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 */
60public void
61present(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 */
69public void
70present(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 */
82public void
83present(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 */
95public void
96present(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 */
106public void
107present(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 */
115public void
116absent(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 */
124public void
125absent(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 */
134public void
135add(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 */
144public void
145add(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 */
153public void
154add(Record record) {
155	newUpdate(record);
156}
157
158/**
159 * Indicates that the records should be inserted into the zone.
160 */
161public void
162add(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 */
171public void
172add(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 */
181public void
182delete(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 */
190public void
191delete(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 */
200public void
201delete(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 */
211public void
212delete(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 */
220public void
221delete(Record record) {
222	newUpdate(record.withDClass(DClass.NONE, 0));
223}
224
225/**
226 * Indicates that the records should be deleted from the zone.
227 */
228public void
229delete(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 */
238public void
239delete(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 */
250public void
251replace(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 */
262public void
263replace(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 */
273public void
274replace(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 */
283public void
284replace(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 */
293public void
294replace(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