KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > xml > DOMBuilder


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.xml;
30
31 import com.caucho.log.Log;
32 import com.caucho.util.CharBuffer;
33 import com.caucho.util.L10N;
34
35 import org.w3c.dom.*;
36 import org.xml.sax.Attributes JavaDoc;
37 import org.xml.sax.ContentHandler JavaDoc;
38 import org.xml.sax.ErrorHandler JavaDoc;
39 import org.xml.sax.Locator JavaDoc;
40 import org.xml.sax.SAXException JavaDoc;
41 import org.xml.sax.SAXParseException JavaDoc;
42
43 import java.io.IOException JavaDoc;
44 import java.util.ArrayList JavaDoc;
45 import java.util.logging.Level JavaDoc;
46 import java.util.logging.Logger JavaDoc;
47
48 /**
49  * XMLWriter to create a DOM document.
50  */

51 public class DOMBuilder implements XMLWriter, ContentHandler JavaDoc, ErrorHandler JavaDoc {
52   static final Logger JavaDoc log = Log.open(DOMBuilder.class);
53   static final L10N L = new L10N(DOMBuilder.class);
54   static final String JavaDoc XMLNS = XmlParser.XMLNS;
55   
56   private QDocument _doc;
57   private Node _top;
58   private Node _node;
59
60   private String JavaDoc _singleText;
61   private CharBuffer _text = new CharBuffer();
62   
63   private boolean _escapeText;
64   private boolean _strictXml;
65
66   // If true, text and cdata sections should be combined.
67
private boolean _isCoalescing = true;
68   // If true, ignorable whitespace is skipped
69
private boolean _skipWhitespace = false;
70
71   private ArrayList JavaDoc<QName> _prefixNames = new ArrayList JavaDoc<QName>();
72   private ArrayList JavaDoc<String JavaDoc> _prefixValues = new ArrayList JavaDoc<String JavaDoc>();
73
74   private Locator JavaDoc _locator;
75   private ExtendedLocator _extLocator;
76   private String JavaDoc _systemId;
77
78   public DOMBuilder()
79   {
80   }
81
82   public void init(Node top)
83   {
84     if (top instanceof QDocument)
85       _doc = (QDocument) top;
86     else
87       _doc = (QDocument) top.getOwnerDocument();
88     _top = top;
89     _node = top;
90     
91     _singleText = null;
92
93     _prefixNames.clear();
94     _prefixValues.clear();
95   }
96
97   public void setSystemId(String JavaDoc systemId)
98   {
99     _systemId = systemId;
100     
101     if (systemId != null && _top instanceof Document) {
102       Document tdoc = (Document) _top;
103       DocumentType dtd = tdoc.getDoctype();
104       if (tdoc instanceof QDocument && dtd == null) {
105     dtd = new QDocumentType(null);
106     ((QDocument) tdoc).setDoctype(dtd);
107       }
108       
109       if (dtd instanceof QDocumentType && dtd.getSystemId() == null)
110         ((QDocumentType) dtd).setSystemId(systemId);
111     }
112
113     if (_doc != null)
114       _doc.setSystemId(systemId);
115   }
116
117   public String JavaDoc getSystemId()
118   {
119     return _systemId;
120   }
121
122   public void setFilename(String JavaDoc filename)
123   {
124     if (filename != null && _top instanceof QDocument) {
125       _doc.setRootFilename(filename);
126     }
127   }
128
129   /**
130    * Set true if we're only handling strict xml.
131    */

132   public void setStrictXML(boolean isStrictXml)
133   {
134     _strictXml = isStrictXml;
135   }
136
137   /**
138    * Set true if text and cdata nodes should be combined.
139    */

140   public void setCoalescing(boolean isCoalescing)
141   {
142     _isCoalescing = isCoalescing;
143   }
144
145   /**
146    * Set true if ignorable whitespace should be skipped.
147    */

148   public void setSkipWhitespace(boolean skipWhitespace)
149   {
150     _skipWhitespace = skipWhitespace;
151   }
152
153   public void setDocumentLocator(Locator JavaDoc loc)
154   {
155     if (_doc == null) {
156       _doc = new QDocument();
157       _node = _doc;
158       _top = _doc;
159     }
160
161     _locator = loc;
162     
163     if (loc instanceof ExtendedLocator)
164       _extLocator = (ExtendedLocator) loc;
165
166     if (_extLocator != null && _doc.getSystemId() == null)
167       _doc.setLocation(_extLocator.getSystemId(),
168                _extLocator.getFilename(),
169                _extLocator.getLineNumber(),
170                _extLocator.getColumnNumber());
171   }
172   
173   public void startPrefixMapping(String JavaDoc prefix, String JavaDoc url)
174   {
175     if (_node == null || _node == _top)
176       _doc.addNamespace(prefix, url);
177
178     if (prefix.equals("")) {
179       _prefixNames.add(new QName(null, "xmlns", XmlParser.XMLNS));
180       _prefixValues.add(url);
181     }
182     else {
183       _prefixNames.add(new QName("xmlns", prefix, XmlParser.XMLNS));
184       _prefixValues.add(url);
185     }
186   }
187   
188   public void endPrefixMapping(String JavaDoc prefix)
189   {
190   }
191
192   public Node getNode()
193   {
194     return _top;
195   }
196
197   public void startDocument()
198   {
199     if (_doc == null) {
200       _doc = new QDocument();
201       _node = _doc;
202       _top = _doc;
203     }
204   }
205
206   public void endDocument()
207     throws SAXException JavaDoc
208   {
209     popText();
210   }
211   
212   public void setLocation(String JavaDoc filename, int line, int column)
213   {
214   }
215
216   public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName)
217     throws IOException JavaDoc
218   {
219     popText();
220     
221     Element elt;
222
223     if (uri != null && ! uri.equals(""))
224       elt = _doc.createElementNS(uri, qName);
225     else if (! qName.equals(""))
226       elt = _doc.createElement(qName);
227     else
228       elt = _doc.createElement(localName);
229     
230     if (_node == _doc) {
231       if (_doc.getDocumentElement() == null)
232         ((QDocument) _doc).setDocumentElement(elt);
233     }
234     
235     _node.appendChild(elt);
236     _node = elt;
237
238     if (_extLocator != null && elt instanceof QElement) {
239       ((QElement) elt).setLocation(_extLocator.getSystemId(),
240                    _extLocator.getFilename(),
241                    _extLocator.getLineNumber(),
242                    _extLocator.getColumnNumber());
243     }
244   }
245
246   public void startElement(QName name, QAttributes attributes)
247     throws SAXException JavaDoc
248   {
249     popText();
250
251     QElement elt = (QElement) _doc.createElementByName(name);
252     _node.appendChild(elt);
253     _node = elt;
254     
255     if (_node == _doc) {
256       if (_doc.getDocumentElement() == null)
257         ((QDocument) _doc).setDocumentElement(elt);
258     }
259
260     for (int i = 0; i < _prefixNames.size(); i++) {
261       QName attrName = _prefixNames.get(i);
262       String JavaDoc value = _prefixValues.get(i);
263
264       elt.setAttribute(attrName, value);
265     }
266
267     _prefixNames.clear();
268     _prefixValues.clear();
269
270     int length = attributes.getLength();
271     for (int i = 0; i < length; i++) {
272       QName attrName = attributes.getName(i);
273       String JavaDoc value = attributes.getValue(i);
274
275       elt.setAttribute(attrName, value);
276     }
277
278     if (_extLocator != null) {
279       elt.setLocation(_extLocator.getSystemId(),
280               _extLocator.getFilename(),
281                       _extLocator.getLineNumber(),
282                       _extLocator.getColumnNumber());
283     }
284     
285     QDocumentType dtd = (QDocumentType) _doc.getDoctype();
286     if (dtd != null)
287       dtd.fillDefaults(elt);
288   }
289
290   public void startElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName,
291                            Attributes JavaDoc attributes)
292     throws SAXException JavaDoc
293   {
294     popText();
295     
296     Element elt;
297
298     if (uri != null && ! uri.equals(""))
299       elt = _doc.createElementNS(uri, qName);
300     else if (! qName.equals(""))
301       elt = _doc.createElement(qName);
302     else
303       elt = _doc.createElement(localName);
304     
305     if (_node == _doc) {
306       if (_doc.getDocumentElement() == null)
307         ((QDocument) _doc).setDocumentElement(elt);
308       else if (_strictXml)
309         throw error(L.l("expected a single top-level element at `{0}'", qName));
310     }
311
312     _node.appendChild(elt);
313     _node = elt;
314
315     int length = attributes.getLength();
316     for (int i = 0; i < length; i++) {
317       String JavaDoc attrUri = attributes.getURI(i);
318       String JavaDoc attrQname = attributes.getQName(i);
319       String JavaDoc value = attributes.getValue(i);
320
321       Attr attr;
322
323       if (attrUri != null && ! attrUri.equals(""))
324         attr = _doc.createAttributeNS(attrUri, attrQname);
325       else if (! attrQname.equals(""))
326         attr = _doc.createAttribute(attrQname);
327       else
328         attr = _doc.createAttribute(attributes.getLocalName(i));
329       
330       attr.setNodeValue(value);
331
332       ((Element) _node).setAttributeNode(attr);
333     }
334
335     if (_extLocator != null)
336       ((QElement) elt).setLocation(_extLocator.getSystemId(),
337                    _extLocator.getFilename(),
338                    _extLocator.getLineNumber(),
339                    _extLocator.getColumnNumber());
340
341     QDocumentType dtd = (QDocumentType) _doc.getDoctype();
342     if (dtd != null) {
343       dtd.fillDefaults((QElement) elt);
344     }
345   }
346
347   public void dtd(QDocumentType dtd)
348   {
349     ((QDocument) _doc).setDoctype(dtd);
350     
351     ((QDocument) _doc).appendChild(dtd);
352   }
353
354   public void attribute(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName,
355                         String JavaDoc value)
356     throws IOException JavaDoc
357   {
358     if (_node instanceof Element) {
359       Attr attr = _doc.createAttributeNS(uri, qName);
360       attr.setNodeValue(value);
361
362       ((Element) _node).setAttributeNode(attr);
363     }
364     else
365       ((QDocument) _node).setAttribute(qName, value);
366   }
367
368   public void endElement(String JavaDoc uri, String JavaDoc localName, String JavaDoc qName)
369   {
370     popText();
371
372     if (_node != null) // XXX:
373
_node = _node.getParentNode();
374     if (_node == null)
375       _node = _doc;
376   }
377
378   public void processingInstruction(String JavaDoc name, String JavaDoc data)
379   {
380     popText();
381     
382     ProcessingInstruction pi = _doc.createProcessingInstruction(name, data);
383
384     _node.appendChild(pi);
385   }
386
387   /**
388    * Handles the callback for a comment.
389    *
390    * @param data the content of the comment.
391    */

392   public void comment(char []buf, int offset, int length)
393     throws SAXException JavaDoc
394   {
395     try {
396       comment(new String JavaDoc(buf, offset, length));
397     } catch (IOException JavaDoc e) {
398       throw new SAXException JavaDoc(e);
399     }
400   }
401
402   /**
403    * Handles the callback for a comment.
404    *
405    * @param data the content of the comment.
406    */

407   public void comment(String JavaDoc data)
408     throws IOException JavaDoc
409   {
410     popText();
411     
412     Comment comment = _doc.createComment(data);
413
414     _node.appendChild(comment);
415   }
416
417   public boolean getEscapeText()
418   {
419     return _escapeText;
420   }
421
422   public void setEscapeText(boolean isEscaped)
423   {
424     _escapeText = isEscaped;
425   }
426
427   public void text(String JavaDoc text)
428     throws IOException JavaDoc
429   {
430     if (_singleText == null && _text.length() == 0) {
431       if (! text.equals(""))
432         _singleText = text;
433     }
434     else if (_singleText != null) {
435       _text.append(_singleText);
436       _text.append(text);
437     }
438     else
439       _text.append(text);
440     
441     if (! _isCoalescing)
442       popText();
443   }
444
445   public void text(char []buffer, int offset, int length)
446     throws IOException JavaDoc
447   {
448     if (length == 0)
449       return;
450     
451     if (_singleText != null) {
452       _singleText = null;
453       _text.append(_singleText);
454     }
455     _text.append(buffer, offset, length);
456     
457     if (! _isCoalescing)
458       popText();
459   }
460
461   /**
462    * Adds text characters to the current document.
463    */

464   public void characters(char []buffer, int offset, int length)
465     throws SAXException JavaDoc
466   {
467     if (length == 0)
468       return;
469     
470     if (_strictXml && _node == _doc) {
471       if (_doc.getDocumentElement() == null) {
472         while (length > 0 && XmlChar.isWhitespace(buffer[offset])) {
473           offset++;
474           length--;
475         }
476
477         for (int i = 0; i < length; i++) {
478           if (buffer[offset + i] == '\n' || buffer[offset + i] == '\r') {
479             length = i;
480             break;
481           }
482         }
483             
484         if (length > 16)
485           length = 16;
486
487         if (length > 0)
488           throw error(L.l("expected top element at `{0}'",
489                           new String JavaDoc(buffer, offset, length)));
490       }
491     }
492     
493     _text.append(buffer, offset, length);
494     
495     /*
496     if (! isCoalescing)
497       popText();
498     */

499   }
500
501   /**
502    * Handles the callback for ignorable whitespace.
503    *
504    * @param buffer the character buffer containing the whitespace.
505    * @param offset starting offset into the character buffer.
506    * @param length number of characters in the buffer.
507    */

508   public void ignorableWhitespace(char []buffer, int offset, int length)
509     throws SAXException JavaDoc
510   {
511     if (! _skipWhitespace)
512       characters(buffer, offset, length);
513   }
514
515   public void entityReference(String JavaDoc name)
516   {
517     popText();
518     
519     QEntityReference er = new QEntityReference(name);
520     er._owner = (QDocument) _doc;
521
522     _node.appendChild(er);
523   }
524
525   public void skippedEntity(String JavaDoc s)
526   {
527     _text.append(s);
528   }
529
530   public void cdata(String JavaDoc text)
531     throws IOException JavaDoc
532   {
533     popText();
534
535     _node.appendChild(_doc.createCDATASection(text));
536   }
537
538   public void cdata(char []buffer, int offset, int length)
539     throws IOException JavaDoc
540   {
541     cdata(new String JavaDoc(buffer, offset, length));
542   }
543
544   private void popText()
545   {
546     if (_singleText != null) {
547       Node text = _doc.createTextNode(_singleText);
548       _node.appendChild(text);
549
550       _singleText = null;
551       return;
552     }
553     
554     if (_text.length() == 0)
555       return;
556     
557     Node text = _doc.createTextNode(_text.toString());
558     _text.clear();
559
560     _node.appendChild(text);
561   }
562   
563   public void fatalError(SAXParseException JavaDoc e)
564     throws SAXException JavaDoc
565   {
566     log.log(Level.FINE, e.toString(), e);
567     
568     throw error(e.getMessage());
569   }
570
571   public void error(SAXParseException JavaDoc e)
572     throws SAXException JavaDoc
573   {
574     log.log(Level.FINER, e.toString(), e);
575     
576     throw error(e.getMessage());
577   }
578
579   public void warning(SAXParseException JavaDoc e)
580     throws SAXException JavaDoc
581   {
582     log.log(Level.FINER, e.toString(), e);
583   }
584     
585   /**
586    * Throws an appropriate error.
587    */

588   public SAXException JavaDoc createError(Exception JavaDoc e)
589   {
590     if (e instanceof SAXException JavaDoc)
591       return (SAXException JavaDoc) e;
592     else
593       return new SAXException JavaDoc(e);
594   }
595
596   /**
597    * Returns a new parse exception with filename and line if available.
598    */

599   XmlParseException error(String JavaDoc text)
600   {
601     if (_extLocator != null)
602       return new XmlParseException(_extLocator.getFilename() + ":" +
603                                    _extLocator.getLineNumber() + ": " + text);
604     else if (_locator != null)
605       return new XmlParseException(_locator.getSystemId() + ":" +
606                                    _locator.getLineNumber() + ": " + text);
607     else
608       return new XmlParseException(text);
609   }
610 }
611
Popular Tags