package net.sf.openrocket.file.simplesax;
import java.io.IOException;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
import net.sf.openrocket.aerodynamics.WarningSet;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.XMLReaderFactory;
/**
* A "simple SAX" XML reader. This system imposes the limit that an XML element may
* contain either textual (non-whitespace) content OR additional elements, but not
* both. This holds true for both the OpenRocket and RockSim design formats and the
* RockSim engine definition format.
* <p>
* The actual handling is performed by subclasses of {@link ElementHandler}. The
* initial handler is provided to the {@link #readXML(InputSource, ElementHandler, WarningSet)}
* method.
*
* @author Sampo Niskanen <sampo.niskanen@iki.fi>
*/
public class SimpleSAX {
static final XMLReaderCache cache = new XMLReaderCache(10);
/**
* Read a simple XML file.
*
* @param source the SAX input source.
* @param initialHandler the initial content handler.
* @param warnings a warning set to store warning (cannot be <code>null</code>).
* @throws IOException if an I/O exception occurs while reading.
* @throws SAXException if e.g. malformed XML is encountered.
*/
public static void readXML(InputSource source, ElementHandler initialHandler,
WarningSet warnings) throws IOException, SAXException {
DelegatorHandler xmlhandler = new DelegatorHandler(initialHandler, warnings);
XMLReader reader = cache.createXMLReader();
reader.setContentHandler(xmlhandler);
reader.setErrorHandler(xmlhandler);
try {
reader.parse(source);
} finally {
reader.setContentHandler(null);
reader.setErrorHandler(null);
cache.releaseXMLReader(reader);
}
}
private static class XMLReaderCache {
private final BlockingQueue<XMLReader> queue;
private XMLReaderCache( int maxSize ) {
this.queue = new LinkedBlockingQueue<XMLReader>(maxSize);
}
private XMLReader createXMLReader() throws SAXException {
XMLReader reader = queue.poll();
if ( reader == null ) {
reader = XMLReaderFactory.createXMLReader();
}
return reader;
}
private void releaseXMLReader( XMLReader reader ) {
// force references to null to encourage garbage collection.
reader.setContentHandler(null);
reader.setErrorHandler(null);
queue.offer( reader );
}
}
}