I think this is a bug. When processing server initiated DNS updates, it is sometimes necessary to delete outdated records from the zone. Consider the following code snippet:
Name name = Name.fromString("sampledns.com.");
Record soarec = new SOARecord(name, DClass.ANY, 0, Name.root, Name.root, 1, 0, 0, 0, 0);
Record nsrec = new NSRecord(name, DClass.ANY, 0, Name.root);
Record rec = Record.newRecord(name, Type.A, DClass.ANY);
Zone zone = new Zone(name, new Record[] {soarec, nsrec, rec});
zone.removeRecord(rec);
Here we create a new zone with 1 record and delete a record later. This code throws the following exception:
java.lang.IllegalStateException: rrset is empty
at org.xbill.DNS.RRset.first(RRset.java:217)
at org.xbill.DNS.RRset.getType(RRset.java:192)
at org.xbill.DNS.Zone.removeRRset(Zone.java:315)
at org.xbill.DNS.Zone.removeRecord(Zone.java:498)
at SampleTest.testRecordRemove(SampleTest.java:31)
...
This is because Zone.removeRRset() calls RRset.getType() and hence RRset.first() on an empty RRset after Zone.removeRecord() has already deleted the only record. We should modify Zone.removeRRset() to check for RRset emptiness before calling RRset.getType(). Something like the following:
private synchronized void removeRRset(Name name, int type) {
Object types = data.get(name);
if (types == null) {
return;
}
if (types instanceof List) {
List list = (List) types;
for (int i = 0; i < list.size(); i++) {
RRset set = (RRset) list.get(i);
if (set.size() == 0 || set.getType() == type) { // check if rrset is empty
list.remove(i);
if (list.size() == 0)
data.remove(name);
return;
}
}
} else {
RRset set = (RRset) types;
if (set.size() != 0 && set.getType() != type) // check if rrset is empty
return;
data.remove(name);
}
}
Modified Zone.java
This has been fixed in version 1.81 of org.xbill.DNS.Zone.java. Thanks.
Ticket moved from /p/dnsjava/patches/13/