⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 master.java

📁 DNS Java 是java实现的DNS
💻 JAVA
字号:
// Copyright (c) 1999-2004 Brian Wellington (bwelling@xbill.org)package org.xbill.DNS;import java.io.*;import java.util.*;/** * A DNS master file parser.  This incrementally parses the file, returning * one record at a time.  When directives are seen, they are added to the * state and used when parsing future records. * * @author Brian Wellington */public class Master {private Name origin;private File file;private Record last = null;private long defaultTTL;private Master included = null;private Tokenizer st;private int currentType;private int currentDClass;private long currentTTL;private boolean needSOATTL;private Generator generator;private List generators;private boolean noExpandGenerate;Master(File file, Name origin, long initialTTL) throws IOException {	if (origin != null && !origin.isAbsolute()) {		throw new RelativeNameException(origin);	}	this.file = file;	st = new Tokenizer(file);	this.origin = origin;	defaultTTL = initialTTL;}/** * Initializes the master file reader and opens the specified master file. * @param filename The master file. * @param origin The initial origin to append to relative names. * @param ttl The initial default TTL. * @throws IOException The master file could not be opened. */publicMaster(String filename, Name origin, long ttl) throws IOException {	this(new File(filename), origin, ttl);}/** * Initializes the master file reader and opens the specified master file. * @param filename The master file. * @param origin The initial origin to append to relative names. * @throws IOException The master file could not be opened. */publicMaster(String filename, Name origin) throws IOException {	this(new File(filename), origin, -1);}/** * Initializes the master file reader and opens the specified master file. * @param filename The master file. * @throws IOException The master file could not be opened. */publicMaster(String filename) throws IOException {	this(new File(filename), null, -1);}/** * Initializes the master file reader. * @param in The input stream containing a master file. * @param origin The initial origin to append to relative names. * @param ttl The initial default TTL. */publicMaster(InputStream in, Name origin, long ttl) {	if (origin != null && !origin.isAbsolute()) {		throw new RelativeNameException(origin);	}	st = new Tokenizer(in);	this.origin = origin;	defaultTTL = ttl;}/** * Initializes the master file reader. * @param in The input stream containing a master file. * @param origin The initial origin to append to relative names. */publicMaster(InputStream in, Name origin) {	this(in, origin, -1);}/** * Initializes the master file reader. * @param in The input stream containing a master file. */publicMaster(InputStream in) {	this(in, null, -1);}private NameparseName(String s, Name origin) throws TextParseException {	try {		return Name.fromString(s, origin);	}	catch (TextParseException e) {		throw st.exception(e.getMessage());	}}private voidparseTTLClassAndType() throws IOException {	String s;	boolean seen_class = false;	// This is a bit messy, since any of the following are legal:	//   class ttl type	//   ttl class type	//   class type	//   ttl type	//   type	seen_class = false;	s = st.getString();	if ((currentDClass = DClass.value(s)) >= 0) {		s = st.getString();		seen_class = true;	}	currentTTL = -1;	try {		currentTTL = TTL.parseTTL(s);		s = st.getString();	}	catch (NumberFormatException e) {		if (defaultTTL >= 0)			currentTTL = defaultTTL;		else if (last != null)			currentTTL = last.getTTL();	}	if (!seen_class) {		if ((currentDClass = DClass.value(s)) >= 0) {			s = st.getString();		} else {			currentDClass = DClass.IN;		}	}	if ((currentType = Type.value(s)) < 0)		throw st.exception("Invalid type '" + s + "'");	// BIND allows a missing TTL for the initial SOA record, and uses	// the SOA minimum value.  If the SOA is not the first record,	// this is an error.	if (currentTTL < 0) {		if (currentType != Type.SOA)			throw st.exception("missing TTL");		needSOATTL = true;		currentTTL = 0;	}}private longparseUInt32(String s) {	if (!Character.isDigit(s.charAt(0)))		return -1;	try {		long l = Long.parseLong(s);		if (l < 0 || l > 0xFFFFFFFFL)			return -1;		return l;	}	catch (NumberFormatException e) {		return -1;	}}private voidstartGenerate() throws IOException {	String s;	int n;	// The first field is of the form start-end[/step]	// Regexes would be useful here.	s = st.getIdentifier();	n = s.indexOf("-");	if (n < 0)		throw st.exception("Invalid $GENERATE range specifier: " + s);	String startstr = s.substring(0, n);	String endstr = s.substring(n + 1);	String stepstr = null;	n = endstr.indexOf("/");	if (n >= 0) {		stepstr = endstr.substring(n + 1);		endstr = endstr.substring(0, n);	}	long start = parseUInt32(startstr);	long end = parseUInt32(endstr);	long step;	if (stepstr != null)		step = parseUInt32(stepstr);	else		step = 1;	if (start < 0 || end < 0 || start > end || step <= 0)		throw st.exception("Invalid $GENERATE range specifier: " + s);	// The next field is the name specification.	String nameSpec = st.getIdentifier();	// Then the ttl/class/type, in the same form as a normal record.	// Only some types are supported.	parseTTLClassAndType();	if (!Generator.supportedType(currentType))		throw st.exception("$GENERATE does not support " +				   Type.string(currentType) + " records");	// Next comes the rdata specification.	String rdataSpec = st.getIdentifier();	// That should be the end.  However, we don't want to move past the	// line yet, so put back the EOL after reading it.	st.getEOL();	st.unget();	generator = new Generator(start, end, step, nameSpec,				  currentType, currentDClass, currentTTL,				  rdataSpec, origin);	if (generators == null)		generators = new ArrayList(1);	generators.add(generator);}private voidendGenerate() throws IOException {	// Read the EOL that we put back before.	st.getEOL();	generator = null;}private RecordnextGenerated() throws IOException {	try {		return generator.nextRecord();	}	catch (Tokenizer.TokenizerException e) {		throw st.exception("Parsing $GENERATE: " + e.getBaseMessage());	}	catch (TextParseException e) {		throw st.exception("Parsing $GENERATE: " + e.getMessage());	}}/** * Returns the next record in the master file.  This will process any * directives before the next record. * @return The next record. * @throws IOException The master file could not be read, or was syntactically * invalid. */public Record_nextRecord() throws IOException {	Tokenizer.Token token;	String s;	if (included != null) {		Record rec = included.nextRecord();		if (rec != null)			return rec;		included = null;	}	if (generator != null) {		Record rec = nextGenerated();		if (rec != null)			return rec;		endGenerate();	}	while (true) {		Name name;		token = st.get(true, false);		if (token.type == Tokenizer.WHITESPACE) {			Tokenizer.Token next = st.get();			if (token.type == Tokenizer.EOL)				continue;			else if (token.type == Tokenizer.EOF)				return null;			else				st.unget();			if (last == null)				throw st.exception("no owner");			name = last.getName();		}		else if (token.type == Tokenizer.EOL)			continue;		else if (token.type == Tokenizer.EOF)			return null;		else if (((String) token.value).charAt(0) == '$') {			s = token.value;			if (s.equalsIgnoreCase("$ORIGIN")) {				origin = st.getName(Name.root);				st.getEOL();				continue;			} else if (s.equalsIgnoreCase("$TTL")) {				defaultTTL = st.getTTL();				st.getEOL();				continue;			} else  if (s.equalsIgnoreCase("$INCLUDE")) {				String filename = st.getString();				File newfile;				if (file != null) {					String parent = file.getParent();					newfile = new File(parent, filename);				} else {					newfile = new File(filename);				}				Name incorigin = origin;				token = st.get();				if (token.isString()) {					incorigin = parseName(token.value,							      Name.root);					st.getEOL();				}				included = new Master(newfile, incorigin,						      defaultTTL);				/*				 * If we continued, we wouldn't be looking in				 * the new file.  Recursing works better.				 */				return nextRecord();			} else  if (s.equalsIgnoreCase("$GENERATE")) {				if (generator != null)					throw new IllegalStateException						("cannot nest $GENERATE");				startGenerate();				if (noExpandGenerate) {					endGenerate();					continue;				}				return nextGenerated();			} else {				throw st.exception("Invalid directive: " + s);			}		} else {			s = token.value;			name = parseName(s, origin);			if (last != null && name.equals(last.getName())) {				name = last.getName();			}		}		parseTTLClassAndType();		last = Record.fromString(name, currentType, currentDClass,					 currentTTL, st, origin);		if (needSOATTL) {			long ttl = ((SOARecord)last).getMinimum();			last.setTTL(ttl);			defaultTTL = ttl;			needSOATTL = false;		}		return last;	}}/** * Returns the next record in the master file.  This will process any * directives before the next record. * @return The next record. * @throws IOException The master file could not be read, or was syntactically * invalid. */public RecordnextRecord() throws IOException {	Record rec = null;	try {		rec = _nextRecord();	}	finally {		if (rec == null) {			st.close();		}	}	return rec;}/** * Specifies whether $GENERATE statements should be expanded.  Whether * expanded or not, the specifications for generated records are available * by calling {@link #generators}.  This must be called before a $GENERATE * statement is seen during iteration to have an effect. */public voidexpandGenerate(boolean wantExpand) {	noExpandGenerate = !wantExpand;}/** * Returns an iterator over the generators specified in the master file; that * is, the parsed contents of $GENERATE statements. * @see Generator */public Iteratorgenerators() {	if (generators != null)		return Collections.unmodifiableList(generators).iterator();	else		return Collections.EMPTY_LIST.iterator();}protected voidfinalize() {	st.close();}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -