/** * Builds a new Record from its textual representation * * @param name The owner name of the record. * @param type The record's type. * @param dclass The record's class. * @param ttl The record's time to live. * @param st A tokenizer containing the textual representation of the rdata. * @param origin The default origin to be appended to relative domain names. * @return The new record * @throws IOException The text format was invalid. */ public static Record fromString( Name name, int type, int dclass, long ttl, Tokenizer st, Name origin) throws IOException { Record rec; if (!name.isAbsolute()) throw new RelativeNameException(name); Type.check(type); DClass.check(dclass); TTL.check(ttl); Tokenizer.Token t = st.get(); if (t.type == Tokenizer.IDENTIFIER && t.value.equals("\\#")) { int length = st.getUInt16(); byte[] data = st.getHex(); if (data == null) { data = new byte[0]; } if (length != data.length) throw st.exception("invalid unknown RR encoding: " + "length mismatch"); DNSInput in = new DNSInput(data); return newRecord(name, type, dclass, ttl, length, in); } st.unget(); rec = getEmptyRecord(name, type, dclass, ttl, true); rec.rdataFromString(st, origin); t = st.get(); if (t.type != Tokenizer.EOL && t.type != Tokenizer.EOF) { throw st.exception("unexpected tokens at end of record"); } return rec; }
/** * Determines if two Records are identical. This compares the name, type, class, and rdata (with * names canonicalized). The TTLs are not compared. * * @param arg The record to compare to * @return true if the records are equal, false otherwise. */ public boolean equals(Object arg) { if (arg == null || !(arg instanceof Record)) return false; Record r = (Record) arg; if (type != r.type || dclass != r.dclass || !name.equals(r.name)) return false; byte[] array1 = rdataToWireCanonical(); byte[] array2 = r.rdataToWireCanonical(); return Arrays.equals(array1, array2); }
private static final Record getEmptyRecord( Name name, int type, int dclass, long ttl, boolean hasData) { Record rec; if (hasData) rec = getTypedObject(type).getObject(); else rec = new EmptyRecord(); rec.name = name; rec.type = type; rec.dclass = dclass; rec.ttl = ttl; return rec; }
private static Record newRecord( Name name, int type, int dclass, long ttl, int length, DNSInput in) throws IOException { Record rec; int recstart; rec = getEmptyRecord(name, type, dclass, ttl, in != null); if (in != null) { if (in.remaining() < length) throw new WireParseException("truncated record"); in.setActive(length); rec.rrFromWire(in); if (in.remaining() > 0) throw new WireParseException("invalid record length"); in.clearActive(); } return rec; }
/** * Compares this Record to another Object. * * @param o The Object to be compared. * @return The value 0 if the argument is a record equivalent to this record; a value less than 0 * if the argument is less than this record in the canonical ordering, and a value greater * than 0 if the argument is greater than this record in the canonical ordering. The canonical * ordering is defined to compare by name, class, type, and rdata. * @throws ClassCastException if the argument is not a Record. */ public int compareTo(Object o) { Record arg = (Record) o; if (this == arg) return (0); int n = name.compareTo(arg.name); if (n != 0) return (n); n = dclass - arg.dclass; if (n != 0) return (n); n = type - arg.type; if (n != 0) return (n); byte[] rdata1 = rdataToWireCanonical(); byte[] rdata2 = arg.rdataToWireCanonical(); for (int i = 0; i < rdata1.length && i < rdata2.length; i++) { n = (rdata1[i] & 0xFF) - (rdata2[i] & 0xFF); if (n != 0) return (n); } return (rdata1.length - rdata2.length); }
private static final Record getTypedObject(int type) { if (type < 0 || type > knownRecords.length) return unknownRecord.getObject(); if (knownRecords[type] != null) return knownRecords[type]; /* Construct the class name by putting the type before "Record". */ String s = Record.class.getPackage().getName() + "." + Type.string(type).replace('-', '_') + "Record"; try { Class c = Class.forName(s); Constructor m = c.getDeclaredConstructor(emptyClassArray); knownRecords[type] = (Record) m.newInstance(emptyObjectArray); } catch (ClassNotFoundException e) { /* This is normal; do nothing */ } catch (Exception e) { if (Options.check("verbose")) System.err.println(e); } if (knownRecords[type] == null) knownRecords[type] = unknownRecord.getObject(); return knownRecords[type]; }
/** * Creates a new record identical to the current record, but with a different class and ttl. This * is most useful for dynamic update. */ Record withDClass(int dclass, long ttl) { Record rec = cloneRecord(); rec.dclass = dclass; rec.ttl = ttl; return rec; }
/** * Creates a new record identical to the current record, but with a different name. This is most * useful for replacing the name of a wildcard record. */ public Record withName(Name name) { if (!name.isAbsolute()) throw new RelativeNameException(name); Record rec = cloneRecord(); rec.name = name; return rec; }
/** * Determines if two Records could be part of the same RRset. This compares the name, type, and * class of the Records; the ttl and rdata are not compared. */ public boolean sameRRset(Record rec) { return (getRRsetType() == rec.getRRsetType() && dclass == rec.dclass && name.equals(rec.name)); }