Dead
[official-gcc.git] / gomp-20050608-branch / libjava / classpath / gnu / xml / dom / ls / SAXEventSink.java
blobaad5ac76e701e2e6f0eaae5c62b7f0ca098dca98
1 /* SAXEventSink.java --
2 Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
4 This file is part of GNU Classpath.
6 GNU Classpath is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
11 GNU Classpath is distributed in the hope that it will be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with GNU Classpath; see the file COPYING. If not, write to the
18 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19 02110-1301 USA.
21 Linking this library statically or dynamically with other modules is
22 making a combined work based on this library. Thus, the terms and
23 conditions of the GNU General Public License cover the whole
24 combination.
26 As a special exception, the copyright holders of this library give you
27 permission to link this library with independent modules to produce an
28 executable, regardless of the license terms of these independent
29 modules, and to copy and distribute the resulting executable under
30 terms of your choice, provided that you also meet, for each linked
31 independent module, the terms and conditions of the license of that
32 module. An independent module is a module which is not derived from
33 or based on this library. If you modify this library, you may extend
34 this exception to your version of the library, but you are not
35 obligated to do so. If you do not wish to do so, delete this
36 exception statement from your version. */
38 package gnu.xml.dom.ls;
40 import java.util.HashSet;
41 import java.util.Iterator;
42 import java.util.LinkedList;
43 import java.util.List;
44 import javax.xml.XMLConstants;
45 import org.w3c.dom.Attr;
46 import org.w3c.dom.DocumentType;
47 import org.w3c.dom.Element;
48 import org.w3c.dom.Entity;
49 import org.w3c.dom.EntityReference;
50 import org.w3c.dom.NamedNodeMap;
51 import org.w3c.dom.Node;
52 import org.w3c.dom.Text;
53 import org.xml.sax.Attributes;
54 import org.xml.sax.ContentHandler;
55 import org.xml.sax.DTDHandler;
56 import org.xml.sax.Locator;
57 import org.xml.sax.SAXException;
58 import org.xml.sax.SAXNotRecognizedException;
59 import org.xml.sax.SAXNotSupportedException;
60 import org.xml.sax.XMLReader;
61 import org.xml.sax.ext.Attributes2;
62 import org.xml.sax.ext.DeclHandler;
63 import org.xml.sax.ext.LexicalHandler;
64 import org.xml.sax.ext.Locator2;
65 import gnu.xml.dom.DomAttr;
66 import gnu.xml.dom.DomDocument;
67 import gnu.xml.dom.DomDoctype;
68 import gnu.xml.dom.DomNode;
70 /**
71 * A SAX content and lexical handler used to construct a DOM document.
73 * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
75 class SAXEventSink
76 implements ContentHandler, LexicalHandler, DTDHandler, DeclHandler
79 private static final String XMLNS_URI = XMLConstants.XMLNS_ATTRIBUTE_NS_URI;
80 private static final String XMLNS_PREFIX = XMLConstants.XMLNS_ATTRIBUTE;
81 private static final HashSet PREDEFINED_ENTITIES = new HashSet();
82 static
84 PREDEFINED_ENTITIES.add("amp");
85 PREDEFINED_ENTITIES.add("lt");
86 PREDEFINED_ENTITIES.add("gt");
87 PREDEFINED_ENTITIES.add("quot");
88 PREDEFINED_ENTITIES.add("apos");
91 boolean namespaceAware;
92 boolean ignoreWhitespace;
93 boolean expandEntityReferences;
94 boolean ignoreComments;
95 boolean coalescing;
97 XMLReader reader; // reference back to the parser to get features
99 DomDocument doc; // document being constructed
100 Node ctx; // current context (parent node)
101 LinkedList entityCtx; // entity context
102 List pending; // namespace nodes waiting for a declaring element
103 Locator locator;
104 boolean inCDATA;
105 boolean inDTD;
106 boolean interrupted;
108 void interrupt()
110 interrupted = true;
113 // -- ContentHandler2 --
115 public void setDocumentLocator(Locator locator)
117 this.locator = locator;
120 public void startDocument()
121 throws SAXException
123 if (namespaceAware)
125 pending = new LinkedList();
127 doc = new DomDocument();
128 doc.setStrictErrorChecking(false);
129 doc.setBuilding(true);
130 ctx = doc;
132 final String FEATURES = "http://xml.org/sax/features/";
133 final String PROPERTIES = "http://xml.org/sax/properties/";
134 final String GNU_PROPERTIES = "http://gnu.org/sax/properties/";
136 boolean standalone = reader.getFeature(FEATURES + "is-standalone");
137 doc.setXmlStandalone(standalone);
140 String version = (String) reader.getProperty(PROPERTIES +
141 "document-xml-version");
142 doc.setXmlVersion(version);
144 catch (SAXNotRecognizedException e)
147 catch (SAXNotSupportedException e)
150 if (locator != null && locator instanceof Locator2)
152 String encoding = ((Locator2) locator).getEncoding();
153 doc.setInputEncoding(encoding);
157 String encoding = (String) reader.getProperty(GNU_PROPERTIES +
158 "document-xml-encoding");
159 doc.setXmlEncoding(encoding);
161 catch (SAXNotRecognizedException e)
164 catch (SAXNotSupportedException e)
169 public void endDocument()
170 throws SAXException
172 doc.setStrictErrorChecking(true);
173 doc.setBuilding(false);
174 DomDoctype doctype = (DomDoctype) doc.getDoctype();
175 if (doctype != null)
177 doctype.makeReadonly();
179 ctx = null;
180 locator = null;
183 public void startPrefixMapping(String prefix, String uri)
184 throws SAXException
186 if (namespaceAware)
188 String nsName = (prefix != null && prefix.length() > 0) ?
189 XMLNS_PREFIX + ":" + prefix : XMLNS_PREFIX;
190 DomAttr ns = (DomAttr) doc.createAttributeNS(XMLNS_URI, nsName);
191 ns.setNodeValue(uri);
192 if (ctx.getNodeType() == Node.ATTRIBUTE_NODE)
194 // Add to owner element
195 Node target = ((Attr) ctx).getOwnerElement();
196 target.getAttributes().setNamedItemNS(ns);
198 else
200 // Add to pending list; namespace node will be inserted when
201 // element is seen
202 pending.add(ns);
207 public void endPrefixMapping(String prefix)
208 throws SAXException
212 public void startElement(String uri, String localName, String qName,
213 Attributes atts)
214 throws SAXException
216 if (interrupted)
218 return;
220 Element element = createElement(uri, localName, qName, atts);
221 // add element to context
222 ctx.appendChild(element);
223 ctx = element;
226 protected Element createElement(String uri, String localName, String qName,
227 Attributes atts)
228 throws SAXException
230 // create element node
231 Element element = namespaceAware ?
232 doc.createElementNS(uri, qName) :
233 doc.createElement(qName);
234 NamedNodeMap attrs = element.getAttributes();
235 if (namespaceAware && !pending.isEmpty())
237 // add pending namespace nodes
238 for (Iterator i = pending.iterator(); i.hasNext(); )
240 Node ns = (Node) i.next();
241 attrs.setNamedItemNS(ns);
243 pending.clear();
245 // add attributes
246 int len = atts.getLength();
247 for (int i = 0; i < len; i++)
249 // create attribute
250 Attr attr = createAttr(atts, i);
251 if (attr != null)
253 // add attribute to element
254 if (namespaceAware)
256 attrs.setNamedItemNS(attr);
258 else
260 attrs.setNamedItem(attr);
264 return element;
267 protected Attr createAttr(Attributes atts, int index)
269 DomAttr attr;
270 if (namespaceAware)
272 String a_uri = atts.getURI(index);
273 String a_qName = atts.getQName(index);
274 attr = (DomAttr) doc.createAttributeNS(a_uri, a_qName);
276 else
278 String a_qName = atts.getQName(index);
279 attr = (DomAttr) doc.createAttribute(a_qName);
281 attr.setNodeValue(atts.getValue(index));
282 if (atts instanceof Attributes2)
284 Attributes2 atts2 = (Attributes2) atts;
285 // TODO attr.setDeclared(atts2.isDeclared(index));
286 attr.setSpecified(atts2.isSpecified(index));
288 return attr;
291 public void endElement(String uri, String localName, String qName)
292 throws SAXException
294 if (interrupted)
296 return;
298 if (namespaceAware)
300 pending.clear();
302 ctx = ctx.getParentNode();
305 public void characters(char[] c, int off, int len)
306 throws SAXException
308 if (interrupted || len < 1)
310 return;
312 ctx.appendChild(createText(c, off, len));
315 protected Text createText(char[] c, int off, int len)
316 throws SAXException
318 Text text = (inCDATA && !coalescing) ?
319 doc.createCDATASection(new String(c, off, len)) :
320 doc.createTextNode(new String(c, off, len));
321 return text;
324 public void ignorableWhitespace(char[] c, int off, int len)
325 throws SAXException
327 if (interrupted)
329 return;
331 if (!ignoreWhitespace)
333 characters(c, off, len);
337 public void processingInstruction(String target, String data)
338 throws SAXException
340 if (interrupted)
342 return;
344 Node pi = createProcessingInstruction(target, data);
345 ctx.appendChild(pi);
348 protected Node createProcessingInstruction(String target, String data)
350 return doc.createProcessingInstruction(target, data);
353 public void skippedEntity(String name)
354 throws SAXException
356 // This callback is totally pointless
359 // -- LexicalHandler --
361 public void startDTD(String name, String publicId, String systemId)
362 throws SAXException
364 if (interrupted)
366 return;
368 Node doctype = createDocumentType(name, publicId, systemId);
369 doc.appendChild(doctype);
370 ctx = doctype;
371 inDTD = true;
374 protected Node createDocumentType(String name, String publicId,
375 String systemId)
377 return new DomDoctype(doc, name, publicId, systemId);
380 public void endDTD()
381 throws SAXException
383 if (interrupted)
385 return;
387 inDTD = false;
388 ctx = ctx.getParentNode();
391 public void startEntity(String name)
392 throws SAXException
394 if (interrupted)
395 return;
396 DocumentType doctype = doc.getDoctype();
397 if (doctype == null)
399 throw new SAXException("SAX parser error: " +
400 "reference to entity in undeclared doctype");
402 if ("[dtd]".equals(name) || name.charAt(0) == '%')
403 return;
404 if (PREDEFINED_ENTITIES.contains(name))
405 return;
406 // Get entity
407 NamedNodeMap entities = doctype.getEntities();
408 Entity entity = (Entity) entities.getNamedItem(name);
409 if (entity == null)
411 throw new SAXException("SAX parser error: " +
412 "reference to undeclared entity: " + name);
414 EntityReference ref = doc.createEntityReference(name);
415 // DomDocument populates with the entity replacement text, remove this
416 Node child = ref.getFirstChild();
417 while (child != null)
419 Node nextChild = child.getNextSibling();
420 ref.removeChild(child);
421 child = nextChild;
423 ctx.appendChild(ref);
424 ctx = ref;
427 public void endEntity(String name)
428 throws SAXException
430 if (interrupted)
431 return;
432 if ("[dtd]".equals(name) || name.charAt(0) == '%')
433 return;
434 if (PREDEFINED_ENTITIES.contains(name))
435 return;
436 // Get entity reference
437 EntityReference ref = (EntityReference) ctx;
438 if (!ref.getNodeName().equals(name))
439 throw new SAXException("expecting end of "+ref.getNodeName()+" entity");
440 ctx = ctx.getParentNode();
441 if (ref instanceof DomNode)
442 ((DomNode) ref).makeReadonly();
443 if (expandEntityReferences)
445 // Move entity content from reference node onto context
446 Node child = ref.getFirstChild();
447 while (child != null)
449 Node nextChild = child.getNextSibling();
450 ctx.appendChild(child);
451 child = nextChild;
453 ctx.removeChild(ref);
457 public void startCDATA()
458 throws SAXException
460 inCDATA = true;
463 public void endCDATA()
464 throws SAXException
466 inCDATA = false;
469 public void comment(char[] c, int off, int len)
470 throws SAXException
472 if (interrupted)
474 return;
476 Node comment = createComment(c, off, len);
477 ctx.appendChild(comment);
480 protected Node createComment(char[] c, int off, int len)
482 return doc.createComment(new String(c, off, len));
485 // -- DTDHandler --
487 public void notationDecl(String name, String publicId, String systemId)
488 throws SAXException
490 if (interrupted)
492 return;
494 if (!inDTD)
495 throw new SAXException("notation decl outside DTD");
496 DomDoctype doctype = (DomDoctype) ctx;
497 doctype.declareNotation(name, publicId, systemId);
500 public void unparsedEntityDecl(String name, String publicId, String systemId,
501 String notationName)
502 throws SAXException
504 if (interrupted)
506 return;
508 if (!inDTD)
509 throw new SAXException("unparsed entity decl outside DTD");
510 DomDoctype doctype = (DomDoctype) ctx;
511 Entity entity = doctype.declareEntity(name, publicId, systemId,
512 notationName);
515 // -- DeclHandler --
517 public void elementDecl(String name, String model)
518 throws SAXException
520 if (interrupted)
522 return;
524 if (!inDTD)
525 throw new SAXException("element decl outside DTD");
526 // Ignore fake element declarations generated by ValidationConsumer.
527 // If an element is not really declared in the DTD it will not be
528 // declared in the document model.
529 if (!(ctx instanceof DomDoctype))
531 return;
533 DomDoctype doctype = (DomDoctype) ctx;
534 doctype.elementDecl(name, model);
537 public void attributeDecl(String eName, String aName, String type,
538 String mode, String value)
539 throws SAXException
541 if (interrupted)
543 return;
545 if (!inDTD)
546 throw new SAXException("attribute decl outside DTD");
547 DomDoctype doctype = (DomDoctype) ctx;
548 doctype.attributeDecl(eName, aName, type, mode, value);
551 public void internalEntityDecl(String name, String value)
552 throws SAXException
554 if (interrupted)
556 return;
558 if (!inDTD)
559 throw new SAXException("internal entity decl outside DTD");
560 DomDoctype doctype = (DomDoctype) ctx;
561 Entity entity = doctype.declareEntity(name, null, null, null);
562 if (entity != null)
564 Node text = doc.createTextNode(value);
565 entity.appendChild(text);
569 public void externalEntityDecl(String name, String publicId, String systemId)
570 throws SAXException
572 if (interrupted)
574 return;
576 if (!inDTD)
577 throw new SAXException("external entity decl outside DTD");
578 DomDoctype doctype = (DomDoctype) ctx;
579 Entity entity = doctype.declareEntity(name, publicId, systemId, null);