KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ozoneDB > xml > DOMFactory


1 /**
2  * org/ozone-db/xml/DOMFactory.java
3  *
4  * The contents of this file are subject to the OpenXML Public
5  * License Version 1.0; you may not use this file except in compliance
6  * with the License. You may obtain a copy of the License at
7  * http://www.openxml.org/license.html
8  *
9  * THIS SOFTWARE IS DISTRIBUTED ON AN "AS IS" BASIS WITHOUT WARRANTY
10  * OF ANY KIND, EITHER EXPRESSED OR IMPLIED. THE INITIAL DEVELOPER
11  * AND ALL CONTRIBUTORS SHALL NOT BE LIABLE FOR ANY DAMAGES AS A
12  * RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
13  * DERIVATIVES. SEE THE LICENSE FOR THE SPECIFIC LANGUAGE GOVERNING
14  * RIGHTS AND LIMITATIONS UNDER THE LICENSE.
15  *
16  * The Initial Developer of this code under the License is Assaf Arkin.
17  * Portions created by Assaf Arkin are Copyright (C) 1998, 1999.
18  * All Rights Reserved.
19  */

20
21 /**
22  * Changes for Persistent DOM running with ozone are
23  * Copyright 1999 by softwarebuero m&b (SMB). All rights reserved.
24  */

25
26 package org.ozoneDB.xml;
27
28 import java.lang.reflect.*;
29 import java.io.*;
30 import java.util.*;
31 import org.w3c.dom.Document JavaDoc;
32 import org.w3c.dom.DocumentType JavaDoc;
33 import org.w3c.dom.html.HTMLDocument;
34 import org.ozoneDB.xml.dom.html.HTMLDocumentImpl;
35 import org.ozoneDB.util.LogWriter;
36 import org.ozoneDB.util.SimpleLogWriter;
37 //import org.openxml.parser.*;
38
//import org.openxml.io.*;
39
//import org.openxml.source.*;
40
//import org.openxml.source.holders.*;
41
//import org.openxml.util.Log;
42

43
44 /**
45  * Factory for XML, HTML and DTD documents, parsers and printers. The factory
46  * has methods for creating new documents, parsers and printers. The exact
47  * type is determined by the document class, this might be {@link Document}
48  * ({@link #DOCUMENT_XML}), {@link HTMLDocument} ({@link #DOCUMENT_HTML}),
49  * {@link DocumentType} ({@link #DOCUMENT_DTD}) or a user document derived from
50  * {@link XMLDocument}.
51  * <P>
52  * The default document type is controlled by the <TT>openxml.document.class</TT>
53  * propety in the OpenXML properties file ({@link <A HREF="properties.html">
54  * openxml.prop</A>}). The parser and printer classes for XML, HTML and DTD
55  * documents are also controlled by the property file.
56  * <P>
57  * The method {@link #createDocument} does not guarantee that it will return
58  * {@link Document}, although this is the default behavior. To obtain a
59  * {@link Document} either pass its class as argument, or call {@link
60  * #createXMLDocument}.
61  * <P>
62  * A newly created parser is only guaranteed to extend {@link Parser}, even
63  * if {@link #DOCUMENT_XML} has been specified as the document type. To create
64  * a document from a user class, either use {@link Source}, or the following
65  * code:
66  * <PRE>
67  * Parser parser;
68  *
69  * parser = DOMFactory.createParser( reader, sourceURI, docClass );
70  * if ( parser instanceof XMLParser )
71  * doc = ( (XMLParser) parser ).parseDocument( null, docClass );
72  * else
73  * doc = parser.parseDocument();
74  * </PRE>
75  *
76  *
77  * @version $Revision: 1.2 $ $Date: 2003/11/17 23:37:10 $
78  * @author <a HREF="mailto:arkin@trendline.co.il">Assaf Arkin</a>
79  * @see org.w3c.dom.Document
80  * @see XMLElement
81  * @see org.ozoneDB.xml.core.XMLCollection
82  */

83 public class DOMFactory extends java.lang.Object JavaDoc {
84
85
86     static LogWriter log = SimpleLogWriter.getInstance();
87     /**
88      * Creates and returns a new XML document. The document type is {@link
89      * Document}.
90      *
91      * @return A new XML document
92      * @see Document
93      */

94     public static Document JavaDoc createXMLDocument() {
95         return createDocument( DOCUMENT_XML );
96     }
97
98
99     /**
100      * Creates and returns a new HTML document. The document type is
101      * {@link HTMLDocument}.
102      *
103      * @return A new XML document
104      * @see HTMLDocument
105      */

106     public static HTMLDocument createHTMLDocument() {
107         return (HTMLDocument)createDocument( DOCUMENT_HTML );
108     }
109
110
111     /**
112      * Creates and returns a new DTD document. The document type is
113      * {@link DTDDocument}.
114      *
115      * @return A new DTD document
116      * @see DTDDocument
117      */

118     public static DTDDocument createDTDDocument() {
119         return (DTDDocument)createDocument( DOCUMENT_DTD );
120     }
121
122
123     /**
124      * Creates and returns a new XML/HTML/DTD document. The document type is
125      * based on <TT>docClass</TT>, which dictates whether the document is XML,
126      * HTML or DTD. If <TT>docClass</TT> is null, the class type is read from
127      * the property <TT>openxml.document.class</TT>, and if that property is
128      * missing, the default {@link Document} is used.
129      * <P>
130      * Note that the returned document type may or may not be {@link Document},
131      * but it must extend {@link Document}, and that is also true for non-XML
132      * documents.
133      *
134      * @return A new XML/HTML/DTD document
135      * @see Document
136      */

137     public static Document JavaDoc createDocument( Class JavaDoc docClass ) {
138         // Returns the document type which is either docClass (must extend
139
// Document), or the class from the properties file, or XMLDocument.
140
docClass = getDocClass( docClass );
141         // Instantiate a new document, report any error encountered and default
142
// to XMLDocument is necessary.
143
if (docClass != null && docClass != Document JavaDoc.class && docClass != XMLDocument.class) {
144             try {
145                 return (Document JavaDoc)docClass.newInstance();
146             } catch (Exception JavaDoc except) {
147                 log.newEntry(DOMFactory.class, "DOMFactory.createDocument: Could not create new instance of document class ["
148                         + docClass.getName() + "] -- defaulting to Document", except, LogWriter.ERROR);
149             }
150         }
151         return new XMLDocument();
152     }
153
154
155     /**
156      * Creates and returns a new XML/HTML/DTD parser. The parser type is
157      * determined by the document class provided in <TT>docClass</TT>, which
158      * dictates whether the parser is XML, HTML or DTD. If <TT>docClass</TT> is
159      * null, the same rules that govern {@link #createDocument} apply here.
160      * <P>
161      * The parser is only guaranteed to extend org.openxml.Parser and will use
162      * {@link #createDocument} to create an instance of the parsed document.
163      * To create a document of a user class, either use org.openxml.Source, or
164      * the following code:
165      * <PRE>
166      * Parser parser;
167      *
168      * parser = DOMFactory.createParser( reader, sourceURI, docClass );
169      * if ( parser instanceof XMLParser )
170      * doc = ( (XMLParser) parser ).parseDocument( null, docClass );
171      * else
172      * doc = parser.parseDocument();
173      * </PRE>
174      *
175      * @param reader A reader to the document source
176      * @param sourceURI The source URI
177      * @param docClass The requested document type
178      * @return A new parser
179      */

180    /*
181    uncommented since we do not use a Parser class
182    public static Parser createParser( Reader reader, String sourceURI, Class docClass ) {
183         String name;
184         Class parserClass;
185         Constructor cnst;
186
187         // Get the specified document class, or the default document class.
188         // Either one is expected as the output of the parser, so work with it.
189         // Based on the document type decide which is the default parser and
190         // the name of the parser class property.
191         docClass = getDocClass( docClass );
192         if (HTMLDocument.class.isAssignableFrom( docClass )) {
193             name = "openxml.parser.html.class";
194             parserClass = HTMLParser.class;
195         } else if (DTDDocument.class.isAssignableFrom( docClass )) {
196             name = "openxml.parser.dtd.class";
197             parserClass = DTDParser.class;
198         } else {
199             name = "openxml.parser.xml.class";
200             parserClass = XMLParser.class;
201         }
202
203         // Given the property name, read its value and if valid, attempt to
204         // load the named parser class. Make sure this class is indeed a
205         // parser. There is no way to check its ability to produce a document
206         // of the requested type: the parser for HTML documents might be rigged
207         // to only produce DTD documents. Such is life.
208         name = getProperty( name );
209         if (name != null) {
210             try {
211                 parserClass = Class.forName( name );
212                 if (!Parser.class.isAssignableFrom( parserClass )) {
213                     parserClass = XMLParser.class;
214                     Log.error( "DOMFactory.createParser: Parser class [" + name
215                             + "] is not a supported parser -- defaulting to XMLParser" );
216                 }
217             } catch (ClassNotFoundException except) {
218                 Log.error( "DOMFactory.createParser: Could not locate parser class [" + name
219                         + "] -- defaulting to XMLParser" );
220             }
221         }
222
223         // Parser class known, find the constructor which accepts a reader and
224         // sourceURI. This is the minimalist constructor for a parser and is
225         // supported by all three parsers. Using that constructor create a new
226         // instance of the parser and return it.
227         if (parserClass != null && parserClass != XMLParser.class) {
228             try {
229                 cnst = parserClass.getConstructor( _parserSignature );
230                 if (cnst != null) {
231                     return (Parser)cnst.newInstance( new Object[] {reader, sourceURI} );
232                 }
233             } catch (Exception except) {
234                 Log.error( "DOMFactory.createParser: Could not create new instance of parser class ["
235                         + parserClass.getName() + "] -- defaulting to XMLParser" );
236                 Log.error( except );
237             }
238         }
239         // Anything fails, or if specifically requested, return the default
240         // XML parser.
241         return new XMLParser( reader, sourceURI );
242     }
243     */

244
245     /**
246      * Creates and returns a new XML parser.
247      *
248      * @param reader A reader to the document source
249      * @param sourceURI The source URI
250      * @return A new parser
251      */

252 /* public static Parser createParser( Reader reader, String sourceName ) throws IOException {
253         return createParser( reader, sourceName, DOCUMENT_XML );
254     } */

255
256
257     /**
258      * Creates and returns a new XML/HTML/DTD parser. The parser type is
259      * determined by the document class provided in <TT>docClass</TT>, which
260      * dictates whether the parser is XML, HTML or DTD. If <TT>docClass</TT> is
261      * null, the same rules that govern {@link #createDocument} apply here.
262      * <P>
263      * The parser is only guaranteed to extend {@link Parser} and will use
264      * {@link #createDocument} to create an instance of the parsed document.
265      * To create a document of a user class, either use {@link Source}, or
266      * the following code:
267      * <PRE>
268      * Parser parser;
269      *
270      * parser = DOMFactory.createParser( reader, sourceURI, docClass );
271      * if ( parser instanceof XMLParser )
272      * doc = ( (XMLParser) parser ).parseDocument( null, docClass );
273      * else
274      * doc = parser.parseDocument();
275      * </PRE>
276      *
277      * @param input An input stream to the document source
278      * @param sourceURI The source URI
279      * @param docClass The requested document type
280      * @return A new parser
281      */

282 /* public static Parser createParser( InputStream stream, String sourceName, Class docClass ) throws IOException {
283         return createParser( new BufferedReader( new InputStreamReader( stream ) ), sourceName, docClass );
284     } */

285
286
287     /**
288      * Creates and returns a new XML parser.
289      *
290      * @param input An input stream to the document source
291      * @param sourceURI The source URI
292      * @return A new parser
293      */

294 /* public static Parser createParser( InputStream stream, String sourceName ) throws IOException {
295         return createParser( new BufferedReader( new InputStreamReader( stream ) ), sourceName, DOCUMENT_XML );
296     }
297     */

298
299     /**
300      * Creates and returns a new XML/HTML/DTD printer. The printer type is
301      * determined by the document class provided in <TT>docClass</TT>, which
302      * dictates whether the printer is XML, HTML or DTD. If <TT>docClass</TT> is
303      * null, the same rules that govern {@link #createDocument} apply here.
304      *
305      * @param writer A writer for the document output
306      * @param mode The printing mode
307      * @param docClass The document type
308      * @return A new printer
309      *
310      * @deprecated
311      * This method has become obsolete in favor of the <a
312      * HREF="x3p/package-summary.html">X3P Publisher and Producer APIs</a>.
313      * This method is temporarily provided for backward compatibility but
314      * will not be included in release 1.1.
315      */

316 /*
317     public static Printer createPrinter( Writer writer, int mode, Class docClass ) throws IOException {
318         Class printerClass;
319         String name;
320         Constructor cnst;
321
322         // Get the specified document class, or the default document class.
323         // Either one is expected as the input to the parser, so work with it.
324         // Based on the document type decide which is the default printer and
325         // the name of the printer class property.
326         docClass = getDocClass( docClass );
327         if (HTMLDocument.class.isAssignableFrom( docClass )) {
328             name = "openxml.printer.html.class";
329             printerClass = HTMLPrinter.class;
330         } else if (DTDDocument.class.isAssignableFrom( docClass )) {
331             name = "openxml.printer.dtd.class";
332             printerClass = DTDPrinter.class;
333         } else {
334             name = "openxml.printer.xml.class";
335             printerClass = XMLPrinter.class;
336         }
337
338         // Given the property name, read its value and if valid, attempt to
339         // load the named printer class. Make sure this class is indeed a
340         // printer. There is no way to check its ability to generate a document
341         // of the requested type: the printer for HTML documents might be rigged
342         // to only generate DTD documents. Such is life.
343         name = getProperty( name );
344         if (name != null) {
345             try {
346                 printerClass = Class.forName( name );
347                 if (!Printer.class.isAssignableFrom( printerClass )) {
348                     printerClass = XMLPrinter.class;
349                     Log.error( "DOMFactory.createPrinter: Printer class [" + name
350                             + "] is not a supported printer -- defaulting to XMLPrinter" );
351                 }
352             } catch (ClassNotFoundException except) {
353                 Log.error( "DOMFactory.createPrinter: Could not locate printer class [" + name
354                         + "] -- defaulting to XMLPrinter" );
355             }
356         }
357
358         // Printer class known, find the constructor which accepts a writer and
359         // printing mode. This is the minimalist constructor for a printer and
360         // is supported by all three printers. Using that constructor create a
361         // new instance of the printer and return it.
362         if (printerClass != null && printerClass != XMLPrinter.class) {
363             try {
364                 cnst = printerClass.getConstructor( _printerSignature );
365                 return (Printer)cnst.newInstance( new Object[] {writer, new Integer( mode )} );
366             } catch (Exception except) {
367                 Log.error( "DOMFactory.createPrinter: Could not create new instance of printer class ["
368                         + printerClass.getName() + "] -- defaulting to XMLPrinter" );
369                 Log.error( except );
370             }
371         }
372         // Anything fails, or if specifically requested, return the default
373         // XML printer.
374         return new XMLPrinter( writer, mode );
375     }
376 */

377
378
379     /**
380      * Creates and returns a new XML printer.
381      *
382      * @param writer A writer for the document output
383      * @param mode The printing mode
384      * @return A new printer
385      *
386      * @deprecated
387      * This method has become obsolete in favor of the <a
388      * HREF="x3p/package-summary.html">X3P Publisher and Producer APIs</a>.
389      * This method is temporarily provided for backward compatibility but
390      * will not be included in release 1.1.
391      */

392 /* public static Printer createPrinter( Writer writer, int mode ) throws IOException {
393         return createPrinter( writer, mode, DOCUMENT_XML );
394     } */

395
396
397     /**
398      * Creates and returns a new XML/HTML/DTD printer. The printer type is
399      * determined by the document class provided in <TT>docClass</TT>, which
400      * dictates whether the printer is XML, HTML or DTD. If <TT>docClass</TT> is
401      * null, the same rules that govern {@link #createDocument} apply here.
402      *
403      * @param output A stream for the document output
404      * @param mode The printing mode
405      * @param docClass The document type
406      * @return A new printer
407      *
408      * @deprecated
409      * This method has become obsolete in favor of the <a
410      * HREF="x3p/package-summary.html">X3P Publisher and Producer APIs</a>.
411      * This method is temporarily provided for backward compatibility but
412      * will not be included in release 1.1.
413      */

414 /* public static Printer createPrinter( OutputStream stream, int mode, Class docClass ) throws IOException {
415         return createPrinter( new XMLStreamWriter( stream ), mode, docClass );
416     } */

417
418
419     /**
420      * Creates and returns a new XML printer.
421      *
422      * @param output A stream for the document output
423      * @param mode The printing mode
424      * @return A new printer
425      *
426      * @deprecated
427      * This method has become obsolete in favor of the <a
428      * HREF="x3p/package-summary.html">X3P Publisher and Producer APIs</a>.
429      * This method is temporarily provided for backward compatibility but
430      * will not be included in release 1.1.
431      */

432 /* public static Printer createPrinter( OutputStream stream, int mode ) throws IOException {
433         return createPrinter( new XMLStreamWriter( stream ), mode, DOCUMENT_XML );
434     } */

435
436
437     /**
438      * Returns the property from the OpenXML properties file.
439      *
440      * @param name The property name
441      * @return Property value or null
442      */

443     public static String JavaDoc getProperty( String JavaDoc name ) {
444         return getProperties().getProperty( name );
445     }
446
447
448     /**
449      * Returns the properties list from the OpenXML properties file. If this
450      * property list is changed, changes will affect the behavior of the factory
451      * and other OpenXML elements.
452      *
453      * @return The properties list
454      */

455     public static Properties getProperties() {
456         String JavaDoc className;
457         Class JavaDoc docClass;
458
459         if (_xmlProps == null) {
460             _xmlProps = new Properties();
461             try {
462                 _xmlProps.load( DOMFactory.class.getResourceAsStream( RESOURCE_PROPS ) );
463             } catch (Exception JavaDoc except) {
464                 log.newEntry(DOMFactory.class, "DOMFactory.getProperties: Failed to load properties from resource [" + RESOURCE_PROPS
465                         + "]", except, LogWriter.ERROR );
466             }
467         }
468         return _xmlProps;
469     }
470
471
472     /**
473      * Returns the specified document class, or the properties file specified
474      * class, or the default. If the specified document class is not valid, a
475      * runtime exception is thrown. If the specified class is null, the name
476      * is read from the properties file and used as the based class. If that
477      * property is missing or not a valid class, the default document class
478      * ({@link Document}) is used.
479      *
480      * @param docClass The specified document class, or null
481      * @return A valid document class, extending {@link Document}
482      */

483     public static Class JavaDoc getDocClass( Class JavaDoc docClass ) {
484         String JavaDoc prop;
485
486         // If the specified document class is invalid, throw an exception,
487
// as we do not want to assume default behavior.
488
if (docClass != null) {
489             if (docClass == DocumentType JavaDoc.class || docClass == DTDDocument.class) {
490                 return DTDDocument.class;
491             }
492             if (!Document JavaDoc.class.isAssignableFrom( docClass )) {
493                 throw new IllegalArgumentException JavaDoc( "Requested document class is not a valid class." );
494             }
495         }
496         // Read the property from the properties file and if not missing,
497
// attempt to load the named class. If the named class does not extend
498
// document, sadly it must be disposed of.
499
prop = getProperty( "openxml.document.class" );
500         if (prop != null) {
501             try {
502                 docClass = Class.forName( prop );
503                 if (!Document JavaDoc.class.isAssignableFrom( docClass )) {
504                     docClass = null;
505                     log.newEntry(DOMFactory.class, "DOMFactory.getDocClass: Document class [" + prop
506                             + "] is not a supported document class -- defaulting to Document", LogWriter.ERROR);
507                 }
508             } catch (ClassNotFoundException JavaDoc except) {
509                 log.newEntry(DOMFactory.class, "DOMFactory.getDocClass: Could not locate document class [" + prop
510                         + "] -- defaulting to Document", LogWriter.ERROR );
511             }
512         }
513         // The default is Document.
514
if (docClass == null) {
515             docClass = DOCUMENT_XML;
516         }
517         return docClass;
518     }
519
520
521 /* public static Source newSource() {
522         getHolderFinder();
523         return new SourceImpl();
524     } */

525
526
527     /**
528      * Returns a singleton holder finder. This finder has default holder factories
529      * registered for handling network, file, JAR and CLASSPATH document sources,
530      * and mapping for built-in DTDs. Additional holder factories and Xcatalogs
531      * may be specified in the properties file and are loaded and registered the
532      * first time this method is called.
533      *
534      * @return An holder finder
535      */

536 /* public static HolderFinder getHolderFinder() {
537         XCatalog catalog;
538         String prop;
539         StringTokenizer tokenizer;
540
541         if (_finder == null) {
542             _finder = HolderFinderImpl.getHolderFinder();
543             catalog = XCatalogFactory.findCatalog( MAIN_CATALOG );
544             if (catalog != null) {
545                 _finder.registerFactory( XCatalogFactory.asHolderFactory( catalog ) );
546             }
547
548             prop = DOMFactory.getProperty( "openxml.holder.factories" );
549             if (prop != null) {
550                 tokenizer = new StringTokenizer( prop, ";" );
551                 while (tokenizer.hasMoreTokens()) {
552                     prop = tokenizer.nextToken();
553                     try {
554                         _finder.registerFactory( (HolderFactory)Class.forName( prop ).newInstance() );
555                         Log.info( "DOMHolderFactory.<init>: Registered holder factory [" + prop + "]" );
556                     } catch (Exception except) {
557                         Log.error( "DOMHolderFactory.<init>: Failed to register holder factory [" + prop
558                                 + "] -- class not found or could not be instantiated" );
559                     }
560                 }
561             }
562
563             prop = DOMFactory.getProperty( "openxml.holder.catalogs" );
564             if (prop != null) {
565                 tokenizer = new StringTokenizer( prop, ";" );
566                 while (tokenizer.hasMoreTokens()) {
567                     prop = tokenizer.nextToken();
568                     try {
569                         catalog = XCatalogFactory.findCatalog( prop );
570
571                         _finder.registerFactory( XCatalogFactory.asHolderFactory( catalog ) );
572                         Log.info( "DOMHolderFactory.<init>: Registered XCatalog from [" + prop + "]" );
573                     } catch (Exception except) {
574                         Log.error( "DOMHolderFactory.<init>: Failed to register XCatalog from [" + prop
575                                 + "] -- catalog not found or could not be loaded" );
576                     }
577                 }
578             }
579         }
580         return _finder;
581     } */

582
583
584     /**
585      * XML document class. Can be used to request a new XML document, XML
586      * parser or XML printer. Will produce a document of type {@link
587      * Document}.
588      */

589     public final static Class JavaDoc DOCUMENT_XML = Document JavaDoc.class;
590
591
592     /**
593      * HTML document class. Can be used to request a new HTML document, HTML
594      * parser or HTML printer. Will produce a document of type {@link
595      * HTMLDocument}.
596      */

597     public final static Class JavaDoc DOCUMENT_HTML = HTMLDocumentImpl.class;
598
599
600     /**
601      * DTD document class. Can be used to request a new DTD document, DTD
602      * parser or DTD printer. Will produce a document of type {@link
603      * DTDDocument}.
604      */

605     public final static Class JavaDoc DOCUMENT_DTD = DocumentType JavaDoc.class;
606
607
608     /**
609      * Holds the properties for the factory. This object is created on-demand
610      * when a property is first accessed.
611      */

612     private static Properties _xmlProps;
613
614
615     /**
616      * Holds a singleton holder finder.
617      */

618     //private static HolderFinder _finder;
619

620
621     /**
622      * The signature for the constructor of a parser class (class that
623      * implemented org.openxml.Parser). Accepts <TT>reader</TT> and
624      * <TT>docClass</TT>.
625      */

626     private final static Class JavaDoc[] _parserSignature = new Class JavaDoc[] {Reader.class, String JavaDoc.class};
627
628
629     /**
630      * The signature for the constructor of a printer class (class that
631      * implemented {@link Printer}). Accepts <TT>writer</TT> and <TT>mode</TT>.
632      */

633     private final static Class JavaDoc[] _printerSignature = new Class JavaDoc[] {Writer.class, int.class};
634
635
636     /**
637      * Identifies the properties file as a resource. The named resource will
638      * be loaded with the DOMFactory class loader. If the resource exists in
639      * a different package, the full package path must be included, preceded
640      * with '/'.
641      */

642     private final static String JavaDoc RESOURCE_PROPS = "openxml.properties";
643
644
645     private final static String JavaDoc MAIN_CATALOG = "res:/org/openxml/source/dtd-catalog/catalog.xml";
646
647
648 }
649
Popular Tags