001: package com.jclark.xml.sax;
002:
003: import com.jclark.xml.parse.*;
004: import com.jclark.xml.parse.base.*;
005: import java.net.URL;
006: import java.net.MalformedURLException;
007: import java.io.InputStream;
008: import java.io.Reader;
009: import java.io.IOException;
010: import java.util.Enumeration;
011: import org.xml.sax.SAXException;
012:
013: /**
014: * An implementation of SAX 1.0 on top of the com.jclark.xml.parse package.
015: * Note that:
016: * <UL>
017: * <LI>the <code>Locator</code> will provide information only for
018: * <code>startElement</code> and <code>processingInstruction</code>
019: * events;
020: * <LI>the line and column number returned by <code>Locator</code>
021: * will correspond to the first character of the document event
022: * not the character following the document event as specified by SAX;
023: * <LI>neither a <code>Locator</code> nor a <code>SAXParseException</code>
024: * will provide information about an entity's public identifier;
025: * <LI>the <code>Locator</code> object will be an instance of
026: * <code>com.jclark.xml.sax.Locator</code> which extends
027: * <code>org.xml.sax.Locator</code>;
028: * <LI>the only kind of error that is reported is a fatal error.
029: * </UL>
030: * @see Locator
031: * @version $Revision: 1.16 $ $Date: 1998/12/28 08:12:30 $
032: */
033: public class Driver extends ApplicationImpl implements
034: org.xml.sax.Parser, EntityManager, org.xml.sax.AttributeList,
035: Locator {
036: private org.xml.sax.EntityResolver entityResolver;
037: private org.xml.sax.DocumentHandler documentHandler;
038: private org.xml.sax.ErrorHandler errorHandler;
039: private org.xml.sax.DTDHandler dtdHandler;
040: private Parser parser = new ParserImpl();
041:
042: private StartElementEvent event;
043: private LocatedEvent locatedEvent;
044: private static final int INIT_DATA_BUF_SIZE = 80;
045: private char[] dataBuf = new char[INIT_DATA_BUF_SIZE];
046: private int dataBufUsed = 0;
047: private final static int UNKNOWN_INDEX = -2;
048: private int idAttributeIndex;
049:
050: public Driver() {
051: org.xml.sax.HandlerBase handler = new org.xml.sax.HandlerBase();
052: this .documentHandler = handler;
053: this .dtdHandler = handler;
054: this .errorHandler = handler;
055: this .entityResolver = handler;
056: parser.setApplication(this );
057: parser.setEntityManager(this );
058: }
059:
060: public void setEntityResolver(org.xml.sax.EntityResolver resolver) {
061: this .entityResolver = resolver;
062: }
063:
064: public void setDocumentHandler(org.xml.sax.DocumentHandler handler) {
065: this .documentHandler = handler;
066: }
067:
068: public void setDTDHandler(org.xml.sax.DTDHandler handler) {
069: this .dtdHandler = handler;
070: }
071:
072: public void setErrorHandler(org.xml.sax.ErrorHandler handler) {
073: this .errorHandler = handler;
074: }
075:
076: public void setLocale(java.util.Locale locale) {
077: parser.setLocale(locale);
078: }
079:
080: public void parse(String systemId) throws SAXException, IOException {
081: parse(new org.xml.sax.InputSource(systemId));
082: }
083:
084: public void parse(org.xml.sax.InputSource in) throws SAXException,
085: IOException {
086:
087: documentHandler.setDocumentLocator(this );
088: try {
089: parser.parseDocument(openInputSource(in));
090: } catch (WrapperException e) {
091: throw e.getWrapped();
092: }
093:
094: catch (NotWellFormedException e) {
095: errorHandler.fatalError(new org.xml.sax.SAXParseException(e
096: .getMessageWithoutLocation(), null, e
097: .getEntityLocation(), e.getLineNumber(), e
098: .getColumnNumber()));
099: }
100:
101: catch (ApplicationException e) {
102: throw (SAXException) e.getException();
103: }
104:
105: }
106:
107: public void startDocument() throws SAXException {
108: documentHandler.startDocument();
109: }
110:
111: public void startElement(StartElementEvent event)
112: throws SAXException {
113: flushData();
114: this .event = event;
115: this .locatedEvent = event;
116: this .idAttributeIndex = UNKNOWN_INDEX;
117: documentHandler.startElement(event.getName(), this );
118: this .locatedEvent = null;
119: }
120:
121: public void characterData(CharacterDataEvent event) {
122: int need = event.getLengthMax() + dataBufUsed;
123: if (need > dataBuf.length) {
124: int newLength = dataBuf.length << 1;
125: while (need > newLength)
126: newLength <<= 1;
127: char[] tem = dataBuf;
128: dataBuf = new char[newLength];
129: if (dataBufUsed > 0)
130: System.arraycopy(tem, 0, dataBuf, 0, dataBufUsed);
131: }
132: dataBufUsed += event.copyChars(dataBuf, dataBufUsed);
133: }
134:
135: private final void flushData() throws SAXException {
136: if (dataBufUsed > 0) {
137: documentHandler.characters(dataBuf, 0, dataBufUsed);
138: dataBufUsed = 0;
139: }
140:
141: }
142:
143: public void endElement(EndElementEvent event) throws SAXException {
144: flushData();
145: documentHandler.endElement(event.getName());
146: }
147:
148: public void processingInstruction(ProcessingInstructionEvent event)
149: throws SAXException {
150: flushData();
151: this .locatedEvent = event;
152: documentHandler.processingInstruction(event.getName(), event
153: .getInstruction());
154: this .locatedEvent = null;
155: }
156:
157: public void endProlog(EndPrologEvent event) throws SAXException {
158: if (dtdHandler == null)
159: return;
160:
161: DTD dtd = event.getDTD();
162:
163: for (Enumeration enum = dtd.entityNames(DTD.NOTATION);
164: enum.hasMoreElements(); ) {
165: String name = (String)enum.nextElement();
166: Entity entity = dtd.getEntity(DTD.NOTATION, name);
167: String systemId = entity.getSystemId();
168: if (systemId != null) {
169: try {
170: systemId = new URL(entity.getBase(), systemId).toString();
171: }
172: catch (MalformedURLException e) { }
173: }
174: dtdHandler.notationDecl(name, entity.getPublicId(), systemId);
175: }
176: for (Enumeration enum = dtd.entityNames(DTD.GENERAL_ENTITY);
177: enum.hasMoreElements();) {
178: String name = (String)enum.nextElement();
179: Entity entity = dtd.getEntity(DTD.GENERAL_ENTITY, name);
180: String notationName = entity.getNotationName();
181: if (notationName != null) {
182: String systemId = entity.getSystemId();
183: if (systemId != null) {
184: try {
185: systemId = new URL(entity.getBase(), systemId).toString();
186: }
187: catch (MalformedURLException e) { }
188: }
189: dtdHandler.unparsedEntityDecl(name,
190: entity.getPublicId(),
191: systemId,
192: notationName);
193: }
194: }
195: }
196:
197: public void endDocument() throws SAXException {
198: flushData();
199: documentHandler.endDocument();
200: }
201:
202: public OpenEntity open(String systemId, URL baseURL, String publicId)
203: throws IOException {
204: if (entityResolver != null) {
205: try {
206: String s = systemId;
207: try {
208: s = new URL(baseURL, systemId).toString();
209: } catch (MalformedURLException e) {
210: }
211: org.xml.sax.InputSource inputSource = entityResolver
212: .resolveEntity(publicId, s);
213: if (inputSource != null)
214: return openInputSource(inputSource);
215: } catch (SAXException e) {
216: throw new WrapperException(e);
217: }
218: }
219: URL url = new URL(baseURL, systemId);
220: return new OpenEntity(url.openStream(), url.toString(), url,
221: null);
222: }
223:
224: private OpenEntity openInputSource(
225: org.xml.sax.InputSource inputSource) throws IOException {
226: Reader reader = inputSource.getCharacterStream();
227: String encoding;
228: InputStream in;
229: if (reader != null) {
230: in = new ReaderInputStream(reader);
231: encoding = "UTF-16";
232: } else {
233: in = inputSource.getByteStream();
234: encoding = inputSource.getEncoding();
235: }
236: String systemId = inputSource.getSystemId();
237: URL url = null;
238: if (in == null) {
239: if (systemId == null)
240: return null;
241: url = new URL(systemId);
242: in = url.openStream();
243: } else if (systemId != null) {
244: try {
245: url = new URL(systemId);
246: } catch (MalformedURLException e) {
247: }
248: } else
249: systemId = "(internal)";
250: return new OpenEntity(in, systemId, url, encoding);
251: }
252:
253: public int getLength() {
254: return event.getAttributeCount();
255: }
256:
257: public String getName(int i) {
258: return event.getAttributeName(i);
259: }
260:
261: public String getValue(int i) {
262: return event.getAttributeValue(i);
263: }
264:
265: public String getValue(String name) {
266: return event.getAttributeValue(name);
267: }
268:
269: public String getType(int i) {
270: if (idAttributeIndex == UNKNOWN_INDEX)
271: idAttributeIndex = event.getIdAttributeIndex();
272: return i == idAttributeIndex ? "ID" : "CDATA";
273: }
274:
275: public String getType(String name) {
276: if (idAttributeIndex == UNKNOWN_INDEX)
277: idAttributeIndex = event.getIdAttributeIndex();
278: if (idAttributeIndex >= 0
279: && event.getAttributeName(idAttributeIndex)
280: .equals(name))
281: return "ID";
282: return "CDATA";
283: }
284:
285: public String getSystemId() {
286: if (locatedEvent == null)
287: return null;
288: return locatedEvent.getLocation().getEntityLocation();
289: }
290:
291: public URL getURL() {
292: if (locatedEvent == null)
293: return null;
294: return locatedEvent.getLocation().getEntityBase();
295: }
296:
297: public String getPublicId() {
298: return null;
299: }
300:
301: public int getLineNumber() {
302: if (locatedEvent == null)
303: return -1;
304: return locatedEvent.getLocation().getLineNumber();
305: }
306:
307: public int getColumnNumber() {
308: if (locatedEvent == null)
309: return -1;
310: int col = locatedEvent.getLocation().getColumnNumber();
311: if (col < 0)
312: return col;
313: return col + 1;
314: }
315:
316: public long getByteIndex() {
317: if (locatedEvent == null)
318: return -1;
319: return locatedEvent.getLocation().getByteIndex();
320: }
321: }
|