1d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)
2d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
3d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpackage org.xbill.DNS;
4d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
5d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.io.*;
6d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenimport java.util.*;
7d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
8d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
9d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * A DNS Zone.  This encapsulates all data related to a Zone, and provides
10d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * convenient lookup methods.
11d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen *
12d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @author Brian Wellington
13d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
14d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
15d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic class Zone implements Serializable {
16d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
17d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate static final long serialVersionUID = -9220510891189510942L;
18d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
19d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** A primary zone */
20d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int PRIMARY = 1;
21d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
22d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** A secondary zone */
23d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic static final int SECONDARY = 2;
24d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
25d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Map data;
26d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Name origin;
27d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate Object originNode;
28d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate int dclass = DClass.IN;
29d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate RRset NS;
30d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate SOARecord SOA;
31d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate boolean hasWild;
32d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
33d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenclass ZoneIterator implements Iterator {
34d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	private Iterator zentries;
35d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	private RRset [] current;
36d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	private int count;
37d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	private boolean wantLastSOA;
38d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
39d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	ZoneIterator(boolean axfr) {
40d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		synchronized (Zone.this) {
41d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			zentries = data.entrySet().iterator();
42d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
43d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		wantLastSOA = axfr;
44d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset [] sets = allRRsets(originNode);
45d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		current = new RRset[sets.length];
46d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (int i = 0, j = 2; i < sets.length; i++) {
47d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			int type = sets[i].getType();
48d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (type == Type.SOA)
49d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				current[0] = sets[i];
50d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			else if (type == Type.NS)
51d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				current[1] = sets[i];
52d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			else
53d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				current[j++] = sets[i];
54d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
55d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
56d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
57d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public boolean
58d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	hasNext() {
59d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return (current != null || wantLastSOA);
60d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
61d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
62d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public Object
63d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	next() {
64d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (!hasNext()) {
65d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			throw new NoSuchElementException();
66d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
67d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (current == null) {
68d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			wantLastSOA = false;
69d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return oneRRset(originNode, Type.SOA);
70d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
71d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Object set = current[count++];
72d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (count == current.length) {
73d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			current = null;
74d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			while (zentries.hasNext()) {
75d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				Map.Entry entry = (Map.Entry) zentries.next();
76d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				if (entry.getKey().equals(origin))
77d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					continue;
78d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				RRset [] sets = allRRsets(entry.getValue());
79d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				if (sets.length == 0)
80d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					continue;
81d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				current = sets;
82d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				count = 0;
83d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				break;
84d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			}
85d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
86d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return set;
87d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
88d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
89d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	public void
90d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	remove() {
91d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new UnsupportedOperationException();
92d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
93d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
94d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
95d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
96d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenvalidate() throws IOException {
97d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	originNode = exactName(origin);
98d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (originNode == null)
99d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IOException(origin + ": no data specified");
100d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
101d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	RRset rrset = oneRRset(originNode, Type.SOA);
102d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (rrset == null || rrset.size() != 1)
103d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IOException(origin +
104d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				      ": exactly 1 SOA must be specified");
105d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Iterator it = rrset.rrs();
106d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	SOA = (SOARecord) it.next();
107d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
108d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	NS = oneRRset(originNode, Type.NS);
109d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (NS == null)
110d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IOException(origin + ": no NS set specified");
111d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
112d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
113d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate final void
114d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenmaybeAddRecord(Record record) throws IOException {
115d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int rtype = record.getType();
116d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name name = record.getName();
117d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
118d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (rtype == Type.SOA && !name.equals(origin)) {
119d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IOException("SOA owner " + name +
120d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				      " does not match zone origin " +
121d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				      origin);
122d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
123d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (name.subdomain(origin))
124d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		addRecord(record);
125d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
126d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
127d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
128d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a Zone from the records in the specified master file.
129d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param zone The name of the zone.
130d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param file The master file to read from.
131d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Master
132d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
133d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
134d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenZone(Name zone, String file) throws IOException {
135d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	data = new TreeMap();
136d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
137d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (zone == null)
138d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("no zone name specified");
139d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Master m = new Master(file, zone);
140d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Record record;
141d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
142d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	origin = zone;
143d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	while ((record = m.nextRecord()) != null)
144d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		maybeAddRecord(record);
145d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	validate();
146d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
147d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
148d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
149d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a Zone from an array of records.
150d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param zone The name of the zone.
151d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param records The records to add to the zone.
152d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Master
153d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
154d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
155d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenZone(Name zone, Record [] records) throws IOException {
156d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	data = new TreeMap();
157d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
158d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (zone == null)
159d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("no zone name specified");
160d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	origin = zone;
161d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < records.length; i++)
162d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		maybeAddRecord(records[i]);
163d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	validate();
164d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
165d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
166d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
167d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfromXFR(ZoneTransferIn xfrin) throws IOException, ZoneTransferException {
168d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	data = new TreeMap();
169d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
170d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	origin = xfrin.getName();
171d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	List records = xfrin.run();
172d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (Iterator it = records.iterator(); it.hasNext(); ) {
173d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Record record = (Record) it.next();
174d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		maybeAddRecord(record);
175d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
176d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!xfrin.isAXFR())
177d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("zones can only be " +
178d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						   "created from AXFRs");
179d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	validate();
180d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
181d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
182d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
183d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a Zone by doing the specified zone transfer.
184d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param xfrin The incoming zone transfer to execute.
185d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see ZoneTransferIn
186d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
187d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
188d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenZone(ZoneTransferIn xfrin) throws IOException, ZoneTransferException {
189d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	fromXFR(xfrin);
190d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
191d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
192d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
193d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Creates a Zone by performing a zone transfer to the specified host.
194d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see ZoneTransferIn
195d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
196d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic
197d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenZone(Name zone, int dclass, String remote)
198d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenthrows IOException, ZoneTransferException
199d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen{
200d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	ZoneTransferIn xfrin = ZoneTransferIn.newAXFR(zone, remote, null);
201d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	xfrin.setDClass(dclass);
202d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	fromXFR(xfrin);
203d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
204d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
205d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Returns the Zone's origin */
206d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Name
207d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetOrigin() {
208d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return origin;
209d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
210d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
211d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Returns the Zone origin's NS records */
212d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic RRset
213d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetNS() {
214d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return NS;
215d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
216d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
217d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Returns the Zone's SOA record */
218d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic SOARecord
219d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetSOA() {
220d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return SOA;
221d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
222d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
223d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/** Returns the Zone's class */
224d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic int
225d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChengetDClass() {
226d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return dclass;
227d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
228d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
229d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate synchronized Object
230d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenexactName(Name name) {
231d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return data.get(name);
232d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
233d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
234d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate synchronized RRset []
235d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenallRRsets(Object types) {
236d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (types instanceof List) {
237d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		List typelist = (List) types;
238d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return (RRset []) typelist.toArray(new RRset[typelist.size()]);
239d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else {
240d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset set = (RRset) types;
241d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return new RRset [] {set};
242d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
243d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
244d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
245d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate synchronized RRset
246d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenoneRRset(Object types, int type) {
247d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (type == Type.ANY)
248d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		throw new IllegalArgumentException("oneRRset(ANY)");
249d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (types instanceof List) {
250d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		List list = (List) types;
251d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (int i = 0; i < list.size(); i++) {
252d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			RRset set = (RRset) list.get(i);
253d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (set.getType() == type)
254d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return set;
255d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
256d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else {
257d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset set = (RRset) types;
258d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (set.getType() == type)
259d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return set;
260d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
261d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return null;
262d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
263d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
264d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate synchronized RRset
265d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfindRRset(Name name, int type) {
266d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Object types = exactName(name);
267d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (types == null)
268d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return null;
269d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return oneRRset(types, type);
270d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
271d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
272d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate synchronized void
273d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenaddRRset(Name name, RRset rrset) {
274d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!hasWild && name.isWild())
275d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		hasWild = true;
276d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Object types = data.get(name);
277d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (types == null) {
278d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		data.put(name, rrset);
279d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
280d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
281d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int rtype = rrset.getType();
282d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (types instanceof List) {
283d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		List list = (List) types;
284d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (int i = 0; i < list.size(); i++) {
285d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			RRset set = (RRset) list.get(i);
286d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (set.getType() == rtype) {
287d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				list.set(i, rrset);
288d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return;
289d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			}
290d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
291d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		list.add(rrset);
292d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else {
293d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset set = (RRset) types;
294d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (set.getType() == rtype)
295d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data.put(name, rrset);
296d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else {
297d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			LinkedList list = new LinkedList();
298d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			list.add(set);
299d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			list.add(rrset);
300d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			data.put(name, list);
301d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
302d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
303d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
304d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
305d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate synchronized void
306d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenremoveRRset(Name name, int type) {
307d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Object types = data.get(name);
308d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (types == null) {
309d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return;
310d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
311d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (types instanceof List) {
312d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		List list = (List) types;
313d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (int i = 0; i < list.size(); i++) {
314d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			RRset set = (RRset) list.get(i);
315d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (set.getType() == type) {
316d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				list.remove(i);
317d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				if (list.size() == 0)
318d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen					data.remove(name);
319d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return;
320d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			}
321d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
322d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	} else {
323d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset set = (RRset) types;
324d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (set.getType() != type)
325d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return;
326d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		data.remove(name);
327d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
328d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
329d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
330d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate synchronized SetResponse
331d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenlookup(Name name, int type) {
332d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int labels;
333d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int olabels;
334d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int tlabels;
335d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	RRset rrset;
336d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name tname;
337d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Object types;
338d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	SetResponse sr;
339d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
340d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (!name.subdomain(origin))
341d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return SetResponse.ofType(SetResponse.NXDOMAIN);
342d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
343d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	labels = name.labels();
344d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	olabels = origin.labels();
345d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
346d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (tlabels = olabels; tlabels <= labels; tlabels++) {
347d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		boolean isOrigin = (tlabels == olabels);
348d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		boolean isExact = (tlabels == labels);
349d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
350d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (isOrigin)
351d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			tname = origin;
352d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else if (isExact)
353d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			tname = name;
354d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else
355d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			tname = new Name(name, labels - tlabels);
356d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
357d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		types = exactName(tname);
358d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (types == null)
359d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			continue;
360d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
361d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		/* If this is a delegation, return that. */
362d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (!isOrigin) {
363d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			RRset ns = oneRRset(types, Type.NS);
364d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (ns != null)
365d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return new SetResponse(SetResponse.DELEGATION,
366d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						       ns);
367d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
368d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
369d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		/* If this is an ANY lookup, return everything. */
370d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (isExact && type == Type.ANY) {
371d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sr = new SetResponse(SetResponse.SUCCESSFUL);
372d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			RRset [] sets = allRRsets(types);
373d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			for (int i = 0; i < sets.length; i++)
374d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				sr.addRRset(sets[i]);
375d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return sr;
376d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
377d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
378d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		/*
379d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		 * If this is the name, look for the actual type or a CNAME.
380d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		 * Otherwise, look for a DNAME.
381d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		 */
382d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (isExact) {
383d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rrset = oneRRset(types, type);
384d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (rrset != null) {
385d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				sr = new SetResponse(SetResponse.SUCCESSFUL);
386d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				sr.addRRset(rrset);
387d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return sr;
388d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			}
389d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rrset = oneRRset(types, Type.CNAME);
390d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (rrset != null)
391d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return new SetResponse(SetResponse.CNAME,
392d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						       rrset);
393d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else {
394d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rrset = oneRRset(types, Type.DNAME);
395d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (rrset != null)
396d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return new SetResponse(SetResponse.DNAME,
397d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen						       rrset);
398d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
399d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
400d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		/* We found the name, but not the type. */
401d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (isExact)
402d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return SetResponse.ofType(SetResponse.NXRRSET);
403d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
404d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
405d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (hasWild) {
406d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		for (int i = 0; i < labels - olabels; i++) {
407d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			tname = name.wild(i + 1);
408d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
409d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			types = exactName(tname);
410d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (types == null)
411d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				continue;
412d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
413d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rrset = oneRRset(types, type);
414d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			if (rrset != null) {
415d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				sr = new SetResponse(SetResponse.SUCCESSFUL);
416d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				sr.addRRset(rrset);
417d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen				return sr;
418d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			}
419d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
420d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
421d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
422d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return SetResponse.ofType(SetResponse.NXDOMAIN);
423d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
424d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
425d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
426d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Looks up Records in the Zone.  This follows CNAMEs and wildcards.
427d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The name to look up
428d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The type to look up
429d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return A SetResponse object
430d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see SetResponse
431d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
432d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic SetResponse
433d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfindRecords(Name name, int type) {
434d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return lookup(name, type);
435d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
436d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
437d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
438d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Looks up Records in the zone, finding exact matches only.
439d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param name The name to look up
440d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param type The type to look up
441d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @return The matching RRset
442d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see RRset
443d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
444d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic RRset
445d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenfindExactMatch(Name name, int type) {
446d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Object types = exactName(name);
447d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	if (types == null)
448d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		return null;
449d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return oneRRset(types, type);
450d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
451d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
452d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
453d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds an RRset to the Zone
454d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param rrset The RRset to be added
455d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see RRset
456d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
457d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
458d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenaddRRset(RRset rrset) {
459d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name name = rrset.getName();
460d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	addRRset(name, rrset);
461d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
462d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
463d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
464d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Adds a Record to the Zone
465d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param r The record to be added
466d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record
467d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
468d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
469d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenaddRecord(Record r) {
470d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name name = r.getName();
471d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int rtype = r.getRRsetType();
472d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	synchronized (this) {
473d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset rrset = findRRset(name, rtype);
474d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (rrset == null) {
475d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rrset = new RRset(r);
476d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			addRRset(name, rrset);
477d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		} else {
478d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rrset.addRR(r);
479d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		}
480d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
481d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
482d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
483d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
484d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Removes a record from the Zone
485d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @param r The record to be removed
486d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * @see Record
487d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
488d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic void
489d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenremoveRecord(Record r) {
490d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Name name = r.getName();
491d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	int rtype = r.getRRsetType();
492d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	synchronized (this) {
493d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset rrset = findRRset(name, rtype);
494d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (rrset == null)
495d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			return;
496d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (rrset.size() == 1 && rrset.first().equals(r))
497d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			removeRRset(name, rtype);
498d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		else
499d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			rrset.deleteRR(r);
500d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
501d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
502d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
503d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
504d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an Iterator over the RRsets in the zone.
505d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
506d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Iterator
507d7955ce24d294fb2014c59d11fca184471056f44Shuyi Cheniterator() {
508d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return new ZoneIterator(false);
509d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
510d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
511d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
512d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns an Iterator over the RRsets in the zone that can be used to
513d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * construct an AXFR response.  This is identical to {@link #iterator} except
514d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * that the SOA is returned at the end as well as the beginning.
515d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
516d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic Iterator
517d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChenAXFR() {
518d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return new ZoneIterator(true);
519d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
520d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
521d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenprivate void
522d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChennodeToString(StringBuffer sb, Object node) {
523d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	RRset [] sets = allRRsets(node);
524d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	for (int i = 0; i < sets.length; i++) {
525d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		RRset rrset = sets[i];
526d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Iterator it = rrset.rrs();
527d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		while (it.hasNext())
528d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append(it.next() + "\n");
529d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		it = rrset.sigs();
530d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		while (it.hasNext())
531d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			sb.append(it.next() + "\n");
532d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
533d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
534d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
535d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
536d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the contents of the Zone in master file format.
537d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
538d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic synchronized String
539d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoMasterFile() {
540d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	Iterator zentries = data.entrySet().iterator();
541d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	StringBuffer sb = new StringBuffer();
542d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	nodeToString(sb, originNode);
543d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	while (zentries.hasNext()) {
544d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		Map.Entry entry = (Map.Entry) zentries.next();
545d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen		if (!origin.equals(entry.getKey()))
546d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen			nodeToString(sb, entry.getValue());
547d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	}
548d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return sb.toString();
549d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
550d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
551d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen/**
552d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen * Returns the contents of the Zone as a string (in master file format).
553d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen */
554d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chenpublic String
555d7955ce24d294fb2014c59d11fca184471056f44Shuyi ChentoString() {
556d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen	return toMasterFile();
557d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
558d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen
559d7955ce24d294fb2014c59d11fca184471056f44Shuyi Chen}
560