KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > xml > util > SAXChunkConsumer


1 // You can redistribute this software and/or modify it under the terms of
2
// the Ozone Library License version 1 published by ozone-db.org.
3
//
4
// The original code and portions created by SMB are
5
// Copyright (C) 1997-@year@ by SMB GmbH. All rights reserved.
6
//
7
// $Id: SAXChunkConsumer.java,v 1.4 2003/04/11 13:38:56 per_nyfelt Exp $
8

9 package org.ozoneDB.xml.util;
10
11 import org.w3c.dom.*;
12 import org.xml.sax.*;
13 import org.xml.sax.ext.LexicalHandler JavaDoc;
14 import org.xml.sax.helpers.AttributesImpl JavaDoc;
15 import org.ozoneDB.util.LogWriter;
16 import org.ozoneDB.util.SimpleLogWriter;
17
18 import java.io.IOException JavaDoc;
19 import java.io.Serializable JavaDoc;
20
21
22 /**
23  * Objects of this class can be used to convert a sequence of
24  * byte[] back into a DOM tree or SAX events.
25  * WARNING: Don't reuse instances of this class. Create a new instance for each
26  * chunk set (chunks containing information about the same XML tree).
27  * @version $Revision: 1.4 $ $Date: 2003/04/11 13:38:56 $
28  * @author <a HREF="http://www.smb-tec.com">SMB</a>
29  */

30 public final class SAXChunkConsumer implements ContentHandler, LexicalHandler JavaDoc, Serializable JavaDoc {
31
32     private final Node appendTo;
33
34     protected Node startNode = null;
35
36     protected Node currentNode = null;
37
38     protected final Document domFactory;
39
40     protected final boolean domLevel2;
41
42     protected final ContentHandler contentHandler;
43
44     protected final LexicalHandler JavaDoc lexicalHandler;
45
46     protected final ChunkInputStream chunkInput;
47
48     protected final CompiledXMLInputStream cxmlInput;
49
50     protected int processLevel;
51
52     protected ModifiableNodeList resultNodeList;
53
54     private LogWriter logWriter;
55
56     private void init() {
57         // we are on the client side so we cant use the Env logger
58
logWriter = SimpleLogWriter.getInstance().setDebugLevel(LogWriter.DEBUG);
59     }
60
61     /**
62      * Use this chunk consumer to produce a DOM tree out of the consumed
63      * chunks.
64      * @param domFactory
65      * @param appendTo The node where the newly created DOM tree will be appended to
66      * @throws IllegalArgumentException if the given node was null
67      */

68     public SAXChunkConsumer(Document domFactory, Node appendTo) throws IOException JavaDoc{
69         init();
70         if (domFactory == null) {
71             throw new IllegalArgumentException JavaDoc("provided DOM factory node was null!");
72         }
73
74         this.contentHandler = this;
75         this.lexicalHandler = this;
76
77         this.appendTo = appendTo;
78         this.processLevel = 0;
79
80         this.resultNodeList = new ModifiableNodeList();
81
82         this.domFactory = domFactory;
83        // this.domLevel2 = domFactory.getImplementation().hasFeature("XML", "2.0");
84
this.domLevel2 = false;
85
86         this.chunkInput = new ChunkInputStream(null);
87         this.cxmlInput = new CompiledXMLInputStream(this.chunkInput);
88     }
89
90
91     /**
92      * Use this chunk consumer to produce SAX events out of the consumed chunks.
93      * @param contentHandler the handler the SAX events will be send to
94      * @throws IllegalArgumentException if the given content handler was null
95      */

96     public SAXChunkConsumer(ContentHandler contentHandler) throws IOException JavaDoc{
97         init();
98         if (contentHandler == null) {
99             throw new IllegalArgumentException JavaDoc("provided SAX content handler was null");
100         }
101         this.contentHandler = contentHandler;
102         this.lexicalHandler = (contentHandler instanceof LexicalHandler JavaDoc)
103                 ? (LexicalHandler JavaDoc)contentHandler
104                 : null;
105         this.appendTo = null;
106
107         this.chunkInput = new ChunkInputStream(null);
108         this.cxmlInput = new CompiledXMLInputStream(this.chunkInput);
109
110         this.domLevel2 = false;
111         this.domFactory = null;
112     }
113
114
115     /**
116      * Takes a chunk and produces corresponding SAX events
117      * @param chunkData the chunk containing definitions of events to be thrown
118      * @throws IllegalArgumentException if the given chunk was null
119      */

120     public final void processChunk(byte[] chunkData) throws SAXException, IOException JavaDoc {
121         if (chunkData == null) {
122             throw new IllegalArgumentException JavaDoc("provided event chunk was null");
123         }
124
125         this.chunkInput.setBuffer(chunkData);
126
127         while (this.chunkInput.available() > 0) {
128             switch (cxmlInput.readEvent()) {
129             case CXMLContentHandler.START_DOCUMENT:
130                 if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
131                     logWriter.newEntry(this, "startDocument()", LogWriter.DEBUG3);
132                 }
133                 this.contentHandler.startDocument();
134                 break;
135             case CXMLContentHandler.END_DOCUMENT:
136                 this.contentHandler.endDocument();
137                 return;
138             case CXMLContentHandler.START_PREFIX_MAPPING:
139                 this.contentHandler.startPrefixMapping(cxmlInput.readString(), cxmlInput.readString());
140                 break;
141             case CXMLContentHandler.END_PREFIX_MAPPING:
142                 this.contentHandler.endPrefixMapping(cxmlInput.readString());
143                 break;
144             case CXMLContentHandler.START_ELEMENT:
145                 if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
146                     logWriter.newEntry(this, "startElement()", LogWriter.DEBUG3);
147                 }
148                 int attributes = cxmlInput.readAttributes();
149                 AttributesImpl JavaDoc atts = new AttributesImpl JavaDoc();
150                 for (int i = 0; i < attributes; i++) {
151 // atts.addAttribute(cxmlInput.readString(), cxmlInput.readString(), cxmlInput.readString(),
152
// cxmlInput.readString(), cxmlInput.readString());
153
atts.addAttribute(cxmlInput.readString(), cxmlInput.readString(), cxmlInput.readString(),
154                             cxmlInput.readString(), new String JavaDoc( cxmlInput.readChars() ) );
155                 }
156                 String JavaDoc namespace = cxmlInput.readString();
157                 String JavaDoc localname = cxmlInput.readString();
158                 String JavaDoc qname = cxmlInput.readString();
159                 logWriter.newEntry(this, "namespace=" + namespace + ", localname=" + localname + ", qname=" + qname, LogWriter.DEBUG1);
160
161                 this.contentHandler.startElement( namespace, localname, qname , atts);
162                 break;
163             case CXMLContentHandler.END_ELEMENT:
164                 this.contentHandler.endElement(cxmlInput.readString(), cxmlInput.readString(), cxmlInput.readString());
165                 break;
166             case CXMLContentHandler.CHARACTERS:
167                 char[] chars = cxmlInput.readChars();
168                 this.contentHandler.characters(chars, 0, chars.length);
169                 break;
170             case CXMLContentHandler.IGNORABLE_WHITESPACE:
171                 char[] spaces = cxmlInput.readChars();
172                 this.contentHandler.characters(spaces, 0, spaces.length);
173                 break;
174             case CXMLContentHandler.PROCESSING_INSTRUCTION:
175                 this.contentHandler.processingInstruction(cxmlInput.readString(), cxmlInput.readString());
176                 break;
177             case CXMLContentHandler.COMMENT:
178                 if (this.lexicalHandler != null) {
179                     char[] comment = cxmlInput.readChars();
180                     this.lexicalHandler.comment(comment, 0, comment.length);
181                 }
182                 break;
183             case CXMLContentHandler.START_CDATA:
184                 if (this.lexicalHandler != null) {
185                     this.lexicalHandler.startCDATA();
186                 }
187                 break;
188             case CXMLContentHandler.END_CDATA:
189                 if (this.lexicalHandler != null) {
190                     this.lexicalHandler.endCDATA();
191                 }
192                 break;
193             default:
194                 throw new IOException JavaDoc("parsing error: event not supported: ");
195             }
196         }
197     }
198
199
200     /**
201      * @return the last created result node, if this consumer was initialized
202      * for DOM creation.
203      */

204     public final Node getResultNode() {
205         return startNode;
206     }
207
208
209     /**
210      * @return the result node list, if this consumer was initialized for
211      * DOM creation.
212      */

213     public final NodeList getResultNodeList() {
214         return resultNodeList;
215     }
216
217
218     //
219
// SAX content handler implemenation
220
//
221

222
223     /**
224      * Received notification of the beginning of the document.
225      */

226     public final void startDocument() {
227         if (this.startNode == null) {
228             this.startNode = (this.appendTo != null) ? this.appendTo : this.domFactory;
229         }
230         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
231             logWriter.newEntry(this, "startDocument()", LogWriter.DEBUG3);
232         }
233
234         if (this.startNode.getNodeType() != Node.DOCUMENT_NODE) {
235             throw new IllegalStateException JavaDoc("A document can't be appended to another node!");
236         }
237
238         if (this.startNode.hasChildNodes()) {
239             throw new RuntimeException JavaDoc("The given DOM document must not have children if a whole document shall be converted!");
240         }
241
242         if (this.processLevel != 0) {
243             throw new RuntimeException JavaDoc("startDocument event must not occur within other start-end-event pairs!");
244         }
245
246         this.resultNodeList.addNode(this.startNode);
247         this.currentNode = this.startNode;
248         this.processLevel++;
249     }
250
251
252     /**
253      * Received notification of the end of the document.
254      */

255     public final void endDocument() {
256         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
257             logWriter.newEntry(this, "endDocument()", LogWriter.DEBUG3);
258         }
259
260         this.currentNode = this.currentNode.getParentNode();
261         this.processLevel--;
262     }
263
264
265     /**
266      * Receive notification of the start of an element.
267      * Note: NamespaceImpl handling has to be revised.
268      */

269     public final void startElement(String JavaDoc _namespaceURI, String JavaDoc _localName, String JavaDoc _rawName, Attributes _atts) {
270         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
271             logWriter.newEntry(this, "startElement(...)", LogWriter.DEBUG3);
272         }
273         Element newElem;
274         if (domLevel2) {
275             newElem = domFactory.createElementNS(_namespaceURI, _rawName);
276
277             //add the attributes
278
for (int i = 0; i < _atts.getLength(); i++) {
279                 newElem.setAttributeNS(_atts.getURI(i), _atts.getQName(i), _atts.getValue(i));
280             }
281         } else {
282             newElem = domFactory.createElement(_rawName);
283
284             //add the attributes
285
for (int i = 0; i < _atts.getLength(); i++) {
286                 newElem.setAttribute(_atts.getQName(i), _atts.getValue(i));
287             }
288
289         }
290
291         if (this.processLevel == 0) {
292             this.resultNodeList.addNode(newElem);
293             this.startNode = newElem;
294             this.currentNode = newElem;
295             if (this.appendTo != null) {
296                 this.appendTo.appendChild(newElem);
297             }
298         } else {
299             this.currentNode.appendChild(newElem);
300             this.currentNode = newElem;
301         }
302         this.processLevel++;
303     }
304
305
306     /**
307      * Receive notification of the end of an element.
308      */

309     public final void endElement(String JavaDoc _namespaceURI, String JavaDoc _localName, String JavaDoc _rawName) {
310         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
311             logWriter.newEntry(this, "endElement(...)", LogWriter.DEBUG3);
312         }
313
314         this.currentNode = this.currentNode.getParentNode();
315         this.processLevel--;
316     }
317
318
319     /**
320      * Begin the scope of a prefix-URI NamespaceImpl mapping.
321      */

322     public final void startPrefixMapping(String JavaDoc _prefix, String JavaDoc _uri) {
323         return;
324     }
325
326
327     /**
328      * End the scope of a prefix-URI mapping.
329      */

330     public final void endPrefixMapping(String JavaDoc prefix) {
331         // Ozone is not yet namespace aware, so we ignore the prefix mappings
332
}
333
334
335     /**
336      * Receive notification of character data inside an element.
337      */

338     public final void characters(char[] ch, int start, int length) {
339
340         if ((this.currentNode != null)
341                 && (this.currentNode.getNodeType() == Node.CDATA_SECTION_NODE)) {
342             //we receive a CDATA section
343

344             StringBuffer JavaDoc chars = new StringBuffer JavaDoc();
345
346             chars.append(ch, start, length);
347             chars.append(this.currentNode.getNodeValue());
348             this.currentNode.setNodeValue(chars.toString());
349         } else {
350             //just normal characters
351
Text textNode = this.domFactory.createTextNode(new String JavaDoc(ch, start, length));
352             if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
353                 logWriter.newEntry(this, "characters(...)", LogWriter.DEBUG3);
354             }
355
356             if (this.processLevel == 0) {
357                 this.resultNodeList.addNode(textNode);
358                 this.startNode = textNode;
359                 this.currentNode = textNode;
360                 if (this.appendTo != null) {
361                     this.appendTo.appendChild(textNode);
362                 }
363             } else {
364                 this.currentNode.appendChild(textNode);
365             }
366         }
367     }
368
369
370     /**
371      * Receive notification of a processing instruction.
372      */

373     public final void processingInstruction(String JavaDoc _target, String JavaDoc _data) {
374         ProcessingInstruction piNode = domFactory.createProcessingInstruction(_target, _data);
375         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
376             logWriter.newEntry(this, "processingInstruction(...)", LogWriter.DEBUG3);
377         }
378
379         if (this.processLevel == 0) {
380             this.resultNodeList.addNode(piNode);
381             this.startNode = piNode;
382             this.currentNode = piNode;
383             if (this.appendTo != null) {
384                 this.appendTo.appendChild(piNode);
385             }
386         } else {
387             this.currentNode.appendChild(piNode);
388         }
389     }
390
391
392     /**
393      * Receive notification of a skipped entity.
394      */

395     public final void skippedEntity(java.lang.String JavaDoc _name) {
396         EntityReference erNode = domFactory.createEntityReference(_name);
397         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
398             logWriter.newEntry(this, "skippedEntity(...)", LogWriter.DEBUG3);
399         }
400
401         if (this.processLevel == 0) {
402             this.resultNodeList.addNode(erNode);
403             this.startNode = erNode;
404             this.currentNode = erNode;
405             if (this.appendTo != null) {
406                 this.appendTo.appendChild(erNode);
407             }
408         } else {
409             this.currentNode.appendChild(erNode);
410         }
411     }
412
413
414     /**
415      * Receive notification of ignorable whitespace in element content.
416      */

417     public final void ignorableWhitespace(char[] _ch, int _start, int _length) {
418         Text whitespace = domFactory.createTextNode(new String JavaDoc(_ch, _start, _length));
419         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
420             logWriter.newEntry(this, "ignorableWhitespace(...)", LogWriter.DEBUG3);
421         }
422
423         if (this.processLevel == 0) {
424             this.resultNodeList.addNode(whitespace);
425             this.startNode = whitespace;
426             this.currentNode = whitespace;
427             if (this.appendTo != null) {
428                 this.appendTo.appendChild(whitespace);
429             }
430         } else {
431             this.currentNode.appendChild(whitespace);
432         }
433     }
434
435
436     /**
437      * Receive an object for locating the origin of SAX document events.
438      */

439     public final void setDocumentLocator(Locator locator) {
440     // we don't care about the origin of the document
441
}
442
443
444     //
445
// SAX LexicalHandler implemenation
446
//
447

448
449     public void comment( char[] ch, int start, int length ) throws SAXException {
450
451         Comment commentNode = this.domFactory.createComment(new String JavaDoc(ch, start, length));
452         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
453             logWriter.newEntry(this, "comment(...)", LogWriter.DEBUG3);
454         }
455
456         if (this.processLevel == 0) {
457             this.resultNodeList.addNode(commentNode);
458             this.startNode = commentNode;
459             this.currentNode = commentNode;
460             if (this.appendTo != null) {
461                 this.appendTo.appendChild(commentNode);
462             }
463         } else {
464             this.currentNode.appendChild(commentNode);
465         }
466     }
467
468
469     public void startCDATA() throws SAXException {
470         CDATASection cdata = this.domFactory.createCDATASection("");
471         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
472             logWriter.newEntry(this, "startCDATA(...)", LogWriter.DEBUG3);
473         }
474
475         if (this.processLevel == 0) {
476             this.resultNodeList.addNode(cdata);
477             this.startNode = cdata;
478             this.currentNode = cdata;
479             if (this.appendTo != null) {
480                 this.appendTo.appendChild(cdata);
481             }
482         } else {
483             this.currentNode.appendChild(cdata);
484             this.currentNode = cdata;
485         }
486         this.processLevel++;
487     }
488
489
490     public void endCDATA() throws SAXException {
491         if (logWriter.hasTarget( LogWriter.DEBUG3 )) {
492             logWriter.newEntry(this, "endCDATA(...)", LogWriter.DEBUG3);
493         }
494
495         this.currentNode = this.currentNode.getParentNode();
496         this.processLevel--;
497     }
498
499
500     public void startDTD(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId)
501             throws SAXException {
502         //FIXME(?)
503
//not handled
504
}
505
506
507     public void endDTD() throws SAXException {
508         //FIXME(?)
509
//not handled
510
}
511
512
513     public void startEntity(String JavaDoc name) throws SAXException {
514         //FIXME(?)
515
//not handled
516
}
517
518
519     public void endEntity(String JavaDoc name) throws SAXException {
520         //FIXME(?)
521
//not handled
522
}
523 }
524
Popular Tags