KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > transformation > XMLDBTransformer


1 /*
2  * Copyright 1999-2004 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.transformation;
17
18 import org.apache.avalon.framework.activity.Initializable;
19 import org.apache.avalon.framework.configuration.Configurable;
20 import org.apache.avalon.framework.configuration.Configuration;
21 import org.apache.avalon.framework.configuration.ConfigurationException;
22 import org.apache.avalon.framework.parameters.Parameters;
23
24 import org.apache.cocoon.ProcessingException;
25 import org.apache.cocoon.ResourceNotFoundException;
26 import org.apache.cocoon.caching.CacheableProcessingComponent;
27 import org.apache.cocoon.environment.SourceResolver;
28 import org.apache.cocoon.util.TraxErrorHandler;
29
30 import org.apache.excalibur.source.SourceValidity;
31
32 import org.xml.sax.Attributes JavaDoc;
33 import org.xml.sax.SAXException JavaDoc;
34 import org.xml.sax.helpers.AttributesImpl JavaDoc;
35
36 import org.xmldb.api.DatabaseManager;
37 import org.xmldb.api.base.Collection;
38 import org.xmldb.api.base.Database;
39 import org.xmldb.api.base.Resource;
40 import org.xmldb.api.base.XMLDBException;
41 import org.xmldb.api.modules.CollectionManagementService;
42 import org.xmldb.api.modules.XUpdateQueryService;
43
44 import java.io.IOException JavaDoc;
45 import java.io.Serializable JavaDoc;
46 import java.io.StringWriter JavaDoc;
47
48 import java.util.HashMap JavaDoc;
49 import java.util.Iterator JavaDoc;
50 import java.util.Map JavaDoc;
51 import java.util.Properties JavaDoc;
52
53 import javax.xml.transform.OutputKeys JavaDoc;
54 import javax.xml.transform.TransformerConfigurationException JavaDoc;
55 import javax.xml.transform.TransformerFactory JavaDoc;
56 import javax.xml.transform.sax.SAXTransformerFactory JavaDoc;
57 import javax.xml.transform.sax.TransformerHandler JavaDoc;
58 import javax.xml.transform.stream.StreamResult JavaDoc;
59
60 /**
61  * This transformer allows to perform resource creation, deletion, and
62  * XUpdate command execution in XML:DB. All operations are performed either
63  * in <code>base</code> collection, or context collection, which
64  * is specified as <code>collection</code> attribute on the <code>query</code>
65  * element. Context collection must be specified relative to the base collection.
66  *
67  * <p>Definition:</p>
68  * <pre>
69  * &lt;map:transformer name="xmldb" SRC="org.apache.cocoon.transformation.XMLDBTransformer"&gt;
70  * &lt;!-- Optional driver parameter. Uncomment if you want transformer to register a database.
71  * &lt;driver&gt;org.apache.xindice.client.xmldb.DatabaseImpl&lt;/driver&gt;
72  * --&gt;
73  * &lt;base&gt;xmldb:xindice:///db/collection&lt;/base&gt;
74  * &lt;/map:transformer&gt;
75  * </pre>
76  *
77  * <p>Invocation:</p>
78  * <pre>
79  * &lt;map:transform type="xmldb"&gt;
80  * &lt;map:parameter name="base" value="xmldb:xindice:///db/collection"/&gt;
81  * &lt;/map:transform&gt;
82  * </pre>
83  *
84  * <p>Input XML document example:</p>
85  * <pre>
86  * &lt;page xmlns:db="http://apache.org/cocoon/xmldb/1.0"&gt;
87  * ...
88  * &lt;p&gt;Create XML resource in base collection with specified object ID&lt;/p&gt;
89  * &lt;db:query type="create" oid="xmldb-object-id"&gt;
90  * &lt;page&gt;
91  * XML Object body
92  * &lt;/page&gt;
93  * &lt;/db:query&gt;
94  *
95  * &lt;p&gt;Delete XML resource from the base collection with specified object ID&lt;/p&gt;
96  * &lt;db:query type="delete" oid="xmldb-object-id"/&gt;
97  *
98  * &lt;p&gt;Update XML resource with specified object ID&lt;/p&gt;
99  * &lt;db:query type="update" oid="xmldb-object-id"&gt;
100  * &lt;xu:modifications version="1.0" xmlns:xu="http://www.xmldb.org/xupdate"&gt;
101  * &lt;xu:remove select="/person/phone[@type = 'home']"/&gt;
102  * &lt;xu:update select="/person/phone[@type = 'work']"&gt;
103  * 480-300-3003
104  * &lt;/xu:update&gt;
105  * &lt;/xu:modifications&gt;
106  * &lt;/db:query&gt;
107  *
108  * &lt;p&gt;Create collection nested into the base collection&lt;/p&gt;
109  * &lt;db:query type="create" oid="inner/"/&gt;
110  *
111  * &lt;p&gt;Create XML resource in context collection with specified object ID&lt;/p&gt;
112  * &lt;xmldb:query type="create" collection="inner" oid="xmldb-object-id"&gt;
113  * &lt;page&gt;
114  * XML Object body
115  * &lt;/page&gt;
116  * &lt;/db:query&gt;
117  * ...
118  * &lt;/page&gt;
119  * </pre>
120  *
121  * <p>Output XML document example:</p>
122  * <pre>
123  * &lt;page xmlns:db="http://apache.org/cocoon/xmldb/1.0"&gt;
124  * ...
125  * &lt;db:query type="create" oid="xmldb-object-id" result="success"/&gt;
126  *
127  * &lt;db:query type="delete" oid="xmldb-object-id" result="success"/&gt;
128  *
129  * &lt;db:query type="update" oid="xmldb-object-id" result="failure"&gt;
130  * Resource xmldb-object-id is not found
131  * &lt;/db:query&gt;
132  * ...
133  * &lt;/page&gt;
134  * </pre>
135  *
136  * <p>Known bugs and limitations:</p>
137  * <ul>
138  * <li>No namespaces with Xalan (see AbstractTextSerializer)</li>
139  * </ul>
140  *
141  * @author <a HREF="mailto:vgritsenko@apache.org">Vadim Gritsenko</a>
142  * @version CVS $Id: XMLDBTransformer.java 55759 2004-10-28 01:17:17Z vgritsenko $
143  */

144 public class XMLDBTransformer extends AbstractTransformer
145         implements CacheableProcessingComponent, Configurable, Initializable {
146
147     private static String JavaDoc XMLDB_URI = "http://apache.org/cocoon/xmldb/1.0";
148     private static String JavaDoc XMLDB_QUERY_ELEMENT = "query";
149     private static String JavaDoc XMLDB_QUERY_TYPE_ATTRIBUTE = "type";
150     private static String JavaDoc XMLDB_QUERY_CONTEXT_ATTRIBUTE = "collection";
151     private static String JavaDoc XMLDB_QUERY_OID_ATTRIBUTE = "oid";
152     private static String JavaDoc XMLDB_QUERY_RESULT_ATTRIBUTE = "result";
153
154     /** The trax <code>TransformerFactory</code> used by this transformer. */
155     private SAXTransformerFactory JavaDoc tfactory = null;
156     private Properties JavaDoc format = new Properties JavaDoc();
157
158     /** The map of namespace prefixes. */
159     private Map JavaDoc prefixMap = new HashMap JavaDoc();
160
161     /** XML:DB driver class name (optional) */
162     private String JavaDoc driver = null;
163
164     /** Default collection name. */
165     private String JavaDoc default_base;
166
167     /** Current collection name. */
168     private String JavaDoc local_base;
169
170     /** Current collection name. */
171     private String JavaDoc xbase;
172
173     /** Current collection. */
174     private Collection collection;
175
176     /** Operation. One of: create, delete, update. */
177     private String JavaDoc operation;
178
179     /** Document ID. Can be null if update or insert is performed on collection. */
180     private String JavaDoc key;
181
182     /** Result of current operation. Success or failure. */
183     private String JavaDoc result;
184
185     /** Message in case current operation failed. */
186     private String JavaDoc message;
187
188     private StringWriter JavaDoc queryWriter;
189     private TransformerHandler JavaDoc queryHandler;
190
191     /** True when inside &lt;query&gt; element. */
192     private boolean processing;
193
194
195     public XMLDBTransformer() {
196         format.put(OutputKeys.ENCODING, "utf-8");
197         format.put(OutputKeys.INDENT, "no");
198         format.put(OutputKeys.OMIT_XML_DECLARATION, "yes");
199     }
200
201     public void configure(Configuration configuration) throws ConfigurationException {
202         this.driver = configuration.getChild("driver").getValue(null);
203         if (driver == null) {
204             getLogger().debug("Driver parameter is missing. Transformer will not initialize database.");
205         }
206
207         this.default_base = configuration.getChild("base").getValue(null);
208     }
209
210     /**
211      * Initializes XML:DB database instance if driver class was configured.
212      */

213     public void initialize() throws Exception JavaDoc {
214         if (driver != null) {
215             Class JavaDoc c = Class.forName(driver);
216             Database database = (Database)c.newInstance();
217             DatabaseManager.registerDatabase(database);
218         }
219     }
220
221     /** Setup the transformer. */
222     public void setup(SourceResolver resolver, Map JavaDoc objectModel, String JavaDoc src, Parameters par)
223     throws ProcessingException, SAXException JavaDoc, IOException JavaDoc {
224
225         this.local_base = par.getParameter("base", this.default_base);
226         if (this.local_base == null) {
227             throw new ProcessingException("Required base parameter is missing. Syntax is: xmldb:xindice:///db/collection");
228         }
229
230         try {
231             this.collection = DatabaseManager.getCollection(this.local_base);
232         } catch (XMLDBException e) {
233             throw new ProcessingException("Could not get collection " + this.local_base + ": " + e.errorCode, e);
234         }
235
236         if (this.collection == null) {
237             throw new ResourceNotFoundException("Collection " + this.local_base + " does not exist");
238         }
239     }
240
241     /**
242      * Helper for TransformerFactory.
243      */

244     protected SAXTransformerFactory JavaDoc getTransformerFactory() {
245         if (tfactory == null) {
246             tfactory = (SAXTransformerFactory JavaDoc) TransformerFactory.newInstance();
247             tfactory.setErrorListener(new TraxErrorHandler(getLogger()));
248         }
249         return tfactory;
250     }
251
252     /**
253      * Generate the unique key.
254      * This key must be unique inside the space of this component.
255      * This method must be invoked before the generateValidity() method.
256      *
257      * @return The generated key or <code>null</code> if the component
258      * is currently not cacheable.
259      */

260     public Serializable JavaDoc getKey() {
261         return null;
262     }
263
264     /**
265      * Generate the validity object.
266      * Before this method can be invoked the generateKey() method
267      * must be invoked.
268      *
269      * @return The generated validity object or <code>null</code> if the
270      * component is currently not cacheable.
271      */

272     public SourceValidity getValidity() {
273         return null;
274     }
275
276     /**
277      * Receive notification of the beginning of a document.
278      */

279     public void startDocument() throws SAXException JavaDoc {
280         super.startDocument();
281     }
282
283     /**
284      * Receive notification of the end of a document.
285      */

286     public void endDocument() throws SAXException JavaDoc {
287         super.endDocument();
288     }
289
290     /**
291      * Begin the scope of a prefix-URI Namespace mapping.
292      *
293      * @param prefix The Namespace prefix being declared.
294      * @param uri The Namespace URI the prefix is mapped to.
295      */

296     public void startPrefixMapping(String JavaDoc prefix, String JavaDoc uri) throws SAXException JavaDoc {
297         if (!processing) {
298             super.startPrefixMapping(prefix,uri);
299             prefixMap.put(prefix,uri);
300         } else if (this.queryHandler != null) {
301             this.queryHandler.startPrefixMapping(prefix, uri);
302         }
303     }
304
305     /**
306      * End the scope of a prefix-URI mapping.
307      *
308      * @param prefix The prefix that was being mapping.
309      */

310     public void endPrefixMapping(String JavaDoc prefix) throws SAXException JavaDoc {
311         if (!processing) {
312             super.endPrefixMapping(prefix);
313             prefixMap.remove(prefix);
314         } else if (this.queryHandler != null){
315             this.queryHandler.endPrefixMapping(prefix);
316         }
317     }
318
319     /**
320      * Receive notification of the beginning of an element.
321      *
322      * @param uri The Namespace URI, or the empty string if the element has no
323      * Namespace URI or if Namespace
324      * processing is not being performed.
325      * @param loc The local name (without prefix), or the empty string if
326      * Namespace processing is not being performed.
327      * @param raw The raw XML 1.0 name (with prefix), or the empty string if
328      * raw names are not available.
329      * @param a The attributes attached to the element. If there are no
330      * attributes, it shall be an empty Attributes object.
331      */

332     public void startElement(String JavaDoc uri, String JavaDoc loc, String JavaDoc raw, Attributes JavaDoc a)
333     throws SAXException JavaDoc {
334         if (!processing) {
335             if (XMLDB_URI.equals(uri) && XMLDB_QUERY_ELEMENT.equals(loc)){
336
337                 this.operation = a.getValue(XMLDB_QUERY_TYPE_ATTRIBUTE);
338                 if (!"create".equals(operation) && !"delete".equals(operation) && !"update".equals(operation)) {
339                     throw new SAXException JavaDoc("Supported operation types are: create, delete, update");
340                 }
341
342                 this.key = a.getValue(XMLDB_QUERY_OID_ATTRIBUTE);
343                 if ("delete".equals(operation) && this.key == null) {
344                     throw new SAXException JavaDoc("Object ID attribute is missing on query element");
345                 }
346
347                 this.xbase = a.getValue(XMLDB_QUERY_CONTEXT_ATTRIBUTE);
348
349                 // Start processing
350
result = "failure";
351                 message = null;
352                 processing = true;
353
354                 if ("create".equals(operation) && this.key != null && this.key.endsWith("/")) {
355                 } else if (!"delete".equals(operation)) {
356                     // Prepare SAX query writer
357
queryWriter = new StringWriter JavaDoc(256);
358                     try {
359                         this.queryHandler = getTransformerFactory().newTransformerHandler();
360                         this.queryHandler.setResult(new StreamResult JavaDoc(queryWriter));
361                         this.queryHandler.getTransformer().setOutputProperties(format);
362                     } catch (TransformerConfigurationException JavaDoc e) {
363                         throw new SAXException JavaDoc("Failed to get transformer handler", e);
364                     }
365
366                     // Start query document
367
this.queryHandler.startDocument();
368                     Iterator JavaDoc i = prefixMap.entrySet().iterator();
369                     while (i.hasNext()) {
370                         Map.Entry JavaDoc entry = (Map.Entry JavaDoc)i.next();
371                         this.queryHandler.startPrefixMapping((String JavaDoc)entry.getKey(), (String JavaDoc)entry.getValue());
372                     }
373                 }
374             } else {
375                 super.startElement(uri, loc, raw, a);
376             }
377         } else if (this.queryHandler != null) {
378             this.queryHandler.startElement(uri, loc, raw, a);
379         }
380     }
381
382     /**
383      * Receive notification of the end of an element.
384      *
385      * @param uri The Namespace URI, or the empty string if the element has no
386      * Namespace URI or if Namespace
387      * processing is not being performed.
388      * @param loc The local name (without prefix), or the empty string if
389      * Namespace processing is not being performed.
390      * @param raw The raw XML 1.0 name (with prefix), or the empty string if
391      * raw names are not available.
392      */

393     public void endElement(String JavaDoc uri, String JavaDoc loc, String JavaDoc raw)
394     throws SAXException JavaDoc {
395         if (!processing) {
396             super.endElement(uri,loc,raw);
397         } else {
398             if (XMLDB_URI.equals(uri) && XMLDB_QUERY_ELEMENT.equals(loc)) {
399                 processing = false;
400
401                 String JavaDoc document = null;
402                 if (this.queryHandler != null) {
403                     // Finish building query. Remove existing prefix mappings.
404
Iterator JavaDoc i = prefixMap.entrySet().iterator();
405                     while (i.hasNext()) {
406                         Map.Entry JavaDoc entry = (Map.Entry JavaDoc) i.next();
407                         this.queryHandler.endPrefixMapping((String JavaDoc)entry.getKey());
408                     }
409                     this.queryHandler.endDocument();
410                     document = this.queryWriter.toString();
411                 }
412
413                 // Perform operation
414
Collection collection = null;
415                 try {
416                     // Obtain collection for the current operation
417
collection = (xbase != null)? DatabaseManager.getCollection(local_base + "/" + xbase) : this.collection;
418
419                     if (collection == null) {
420                         message = "Failed to " + operation + " resource " + this.key + ": Collection " + local_base + "/" + xbase + " not found.";
421                         getLogger().debug(message);
422                     } else if ("create".equals(operation)) {
423                         if (key != null && key.endsWith("/")) {
424                             try {
425                                 // Cut trailing '/'
426
String JavaDoc k = this.key.substring(0, this.key.length() - 1);
427                                 CollectionManagementService service =
428                                         (CollectionManagementService) collection.getService("CollectionManagementService", "1.0");
429                                 service.createCollection(k);
430                                 result = "success";
431                             } catch (XMLDBException e) {
432                                 message = "Failed to create collection " + this.key + ": " + e.errorCode;
433                                 getLogger().error(message, e);
434                             }
435                         } else {
436                             try {
437                                 if (key == null) {
438                                     key = collection.createId();
439                                 }
440                                 // Support of binary objects can be added. Content can be obtained using Source.
441
Resource resource = collection.createResource(key, "XMLResource");
442                                 resource.setContent(document);
443                                 collection.storeResource(resource);
444                                 result = "success";
445                                 key = resource.getId();
446                             } catch (XMLDBException e) {
447                                 message = "Failed to create resource " + key + ": " + e.errorCode;
448                                 getLogger().debug(message, e);
449                             }
450                         }
451                     } else if ("delete".equals(operation)) {
452                         if (key != null && key.endsWith("/")) {
453                             try {
454                                 // Cut trailing '/'
455
String JavaDoc k = this.key.substring(0, this.key.length() - 1);
456                                 CollectionManagementService service =
457                                         (CollectionManagementService) collection.getService("CollectionManagementService", "1.0");
458                                 service.removeCollection(k);
459                                 result = "success";
460                             } catch (XMLDBException e) {
461                                 message = "Failed to delete collection " + this.key + ": " + e.errorCode;
462                                 getLogger().error(message, e);
463                             }
464                         } else {
465                             try {
466                                 Resource resource = collection.getResource(this.key);
467                                 if (resource == null) {
468                                     message = "Resource " + this.key + " does not exist";
469                                     getLogger().debug(message);
470                                 } else {
471                                     collection.removeResource(resource);
472                                     result = "success";
473                                 }
474                             } catch (XMLDBException e) {
475                                 message = "Failed to delete resource " + key + ": " + e.errorCode;
476                                 getLogger().debug(message, e);
477                             }
478                         }
479                     } else if ("update".equals(operation)) {
480                         try {
481                             XUpdateQueryService service =
482                                     (XUpdateQueryService) collection.getService("XUpdateQueryService", "1.0");
483                             long count = (this.key == null)?
484                                     service.update(document) : service.updateResource(this.key, document);
485                             message = count + " entries updated.";
486                             result = "success";
487                         } catch (XMLDBException e) {
488                             message = "Failed to update resource " + key + ": " + e.errorCode;
489                             getLogger().debug(message, e);
490                         }
491                     }
492                 } catch (XMLDBException e) {
493                     message = "Failed to get context collection for the query (base: " + local_base + ", context: " + xbase + "): " + e.errorCode;
494                     getLogger().debug(message, e);
495                 } finally {
496                     if (xbase != null && collection != null) {
497                         try {
498                             collection.close();
499                         } catch (XMLDBException ignored) {
500                         }
501                     }
502                 }
503
504
505                 // Report result
506
AttributesImpl JavaDoc attrs = new AttributesImpl JavaDoc();
507                 attrs.addAttribute(null, XMLDB_QUERY_OID_ATTRIBUTE,
508                         XMLDB_QUERY_OID_ATTRIBUTE, "CDATA", this.key);
509                 attrs.addAttribute(null, XMLDB_QUERY_TYPE_ATTRIBUTE,
510                         XMLDB_QUERY_TYPE_ATTRIBUTE, "CDATA", this.operation);
511                 attrs.addAttribute(null, XMLDB_QUERY_RESULT_ATTRIBUTE,
512                         XMLDB_QUERY_RESULT_ATTRIBUTE, "CDATA", result);
513                 super.startElement(uri, loc, raw, attrs);
514                 if (message != null) {
515                     super.characters(message.toCharArray(), 0, message.length());
516                 }
517                 super.endElement(uri, loc, raw);
518             } else if (this.queryHandler != null) {
519                 this.queryHandler.endElement(uri, loc, raw);
520             }
521         }
522     }
523
524     /**
525      * Receive notification of character data.
526      *
527      * @param c The characters from the XML document.
528      * @param start The start position in the array.
529      * @param len The number of characters to read from the array.
530      */

531     public void characters(char c[], int start, int len) throws SAXException JavaDoc {
532         if (!processing) {
533             super.characters(c,start,len);
534         } else if (this.queryHandler != null) {
535             this.queryHandler.characters(c,start,len);
536         }
537     }
538
539     /**
540      * Receive notification of ignorable whitespace in element content.
541      *
542      * @param c The characters from the XML document.
543      * @param start The start position in the array.
544      * @param len The number of characters to read from the array.
545      */

546     public void ignorableWhitespace(char c[], int start, int len) throws SAXException JavaDoc {
547         if (!processing) {
548             super.ignorableWhitespace(c,start,len);
549         } else if (this.queryHandler != null) {
550             this.queryHandler.ignorableWhitespace(c,start,len);
551         }
552     }
553
554     /**
555      * Receive notification of a processing instruction.
556      *
557      * @param target The processing instruction target.
558      * @param data The processing instruction data, or null if none was
559      * supplied.
560      */

561     public void processingInstruction(String JavaDoc target, String JavaDoc data) throws SAXException JavaDoc {
562         if (!processing) {
563             super.processingInstruction(target,data);
564         } else if (this.queryHandler != null) {
565             this.queryHandler.processingInstruction(target,data);
566         }
567     }
568
569     /**
570      * Receive notification of a skipped entity.
571      *
572      * @param name The name of the skipped entity. If it is a parameter
573      * entity, the name will begin with '%'.
574      */

575     public void skippedEntity(String JavaDoc name) throws SAXException JavaDoc {
576         if (!processing) {
577             super.skippedEntity(name);
578         } else if (this.queryHandler != null) {
579             this.queryHandler.skippedEntity(name);
580         }
581     }
582
583     /**
584      * Report the start of DTD declarations, if any.
585      *
586      * @param name The document type name.
587      * @param publicId The declared public identifier for the external DTD
588      * subset, or null if none was declared.
589      * @param systemId The declared system identifier for the external DTD
590      * subset, or null if none was declared.
591      */

592     public void startDTD(String JavaDoc name, String JavaDoc publicId, String JavaDoc systemId) throws SAXException JavaDoc {
593         if (!processing) {
594             super.startDTD(name, publicId, systemId);
595         } else {
596             throw new SAXException JavaDoc(
597                 "Recieved startDTD after beginning SVG extraction process."
598             );
599         }
600     }
601
602     /**
603      * Report the end of DTD declarations.
604      */

605     public void endDTD() throws SAXException JavaDoc {
606         if (!processing) {
607             super.endDTD();
608         } else {
609             throw new SAXException JavaDoc("Recieved endDTD after xmldb element.");
610         }
611     }
612
613     /**
614      * Report the beginning of an entity.
615      *
616      * @param name The name of the entity. If it is a parameter entity, the
617      * name will begin with '%'.
618      */

619     public void startEntity(String JavaDoc name) throws SAXException JavaDoc {
620         if (!processing) {
621             super.startEntity(name);
622         } else if (this.queryHandler != null) {
623             this.queryHandler.startEntity(name);
624         }
625     }
626
627     /**
628      * Report the end of an entity.
629      *
630      * @param name The name of the entity that is ending.
631      */

632     public void endEntity(String JavaDoc name) throws SAXException JavaDoc {
633         if (!processing) {
634             super.endEntity(name);
635         } else if (this.queryHandler != null) {
636             this.queryHandler.endEntity(name);
637         }
638     }
639
640     /**
641      * Report the start of a CDATA section.
642      */

643     public void startCDATA() throws SAXException JavaDoc {
644         if (!processing) {
645             super.startCDATA();
646         } else if (this.queryHandler != null) {
647             this.queryHandler.startCDATA();
648         }
649     }
650
651     /**
652      * Report the end of a CDATA section.
653      */

654     public void endCDATA() throws SAXException JavaDoc {
655         if (!processing) {
656             super.endCDATA();
657         } else if (this.queryHandler != null) {
658             this.queryHandler.endCDATA();
659         }
660     }
661
662     /**
663      * Report an XML comment anywhere in the document.
664      *
665      * @param ch An array holding the characters in the comment.
666      * @param start The starting position in the array.
667      * @param len The number of characters to use from the array.
668      */

669     public void comment(char ch[], int start, int len) throws SAXException JavaDoc {
670         if (!processing) {
671             super.comment(ch, start, len);
672         } else if (this.queryHandler != null) {
673             this.queryHandler.comment(ch, start, len);
674         }
675     }
676
677     public void recycle() {
678         this.prefixMap.clear();
679         this.queryHandler = null;
680         this.queryWriter = null;
681
682         try {
683             if (collection != null) {
684                 collection.close();
685             }
686         } catch (XMLDBException e) {
687             getLogger().error("Failed to close collection " + this.local_base + ". Error " + e.errorCode, e);
688         }
689         collection = null;
690         super.recycle();
691     }
692 }
693
Popular Tags