Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: gnu/xml/dom/ls/DomLSParser.java


1   /* DomLSParser.java -- 
2      Copyright (C) 1999,2000,2001 Free Software Foundation, Inc.
3   
4   This file is part of GNU Classpath.
5   
6   GNU Classpath is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2, or (at your option)
9   any later version.
10  
11  GNU Classpath is distributed in the hope that it will be useful, but
12  WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  General Public License for more details.
15  
16  You should have received a copy of the GNU General Public License
17  along with GNU Classpath; see the file COPYING.  If not, write to the
18  Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19  02110-1301 USA.
20  
21  Linking this library statically or dynamically with other modules is
22  making a combined work based on this library.  Thus, the terms and
23  conditions of the GNU General Public License cover the whole
24  combination.
25  
26  As a special exception, the copyright holders of this library give you
27  permission to link this library with independent modules to produce an
28  executable, regardless of the license terms of these independent
29  modules, and to copy and distribute the resulting executable under
30  terms of your choice, provided that you also meet, for each linked
31  independent module, the terms and conditions of the license of that
32  module.  An independent module is a module which is not derived from
33  or based on this library.  If you modify this library, you may extend
34  this exception to your version of the library, but you are not
35  obligated to do so.  If you do not wish to do so, delete this
36  exception statement from your version. */
37  
38  package gnu.xml.dom.ls;
39  
40  import java.io.File;
41  import java.io.InputStream;
42  import java.io.IOException;
43  import java.net.MalformedURLException;
44  import java.net.URL;
45  import java.util.Arrays;
46  import java.util.List;
47  import javax.xml.parsers.ParserConfigurationException;
48  import javax.xml.parsers.SAXParser;
49  import javax.xml.parsers.SAXParserFactory;
50  import org.w3c.dom.Document;
51  import org.w3c.dom.DOMConfiguration;
52  import org.w3c.dom.DOMException;
53  import org.w3c.dom.DOMStringList;
54  import org.w3c.dom.Node;
55  import org.w3c.dom.ls.DOMImplementationLS;
56  import org.w3c.dom.ls.LSException;
57  import org.w3c.dom.ls.LSInput;
58  import org.w3c.dom.ls.LSParser;
59  import org.w3c.dom.ls.LSParserFilter;
60  import org.xml.sax.EntityResolver;
61  import org.xml.sax.ErrorHandler;
62  import org.xml.sax.InputSource;
63  import org.xml.sax.SAXException;
64  import org.xml.sax.SAXNotRecognizedException;
65  import org.xml.sax.SAXParseException;
66  import org.xml.sax.XMLReader;
67  import gnu.xml.dom.DomDocument;
68  import gnu.xml.dom.DomDOMException;
69  
70  /**
71   * Parser implementation for GNU DOM.
72   *
73   * @author <a href='mailto:dog@gnu.org'>Chris Burdess</a>
74   */
75  public class DomLSParser
76    implements LSParser, DOMConfiguration, DOMStringList, ErrorHandler
77  {
78  
79    private static final List SUPPORTED_PARAMETERS
80      = Arrays.asList(new String[] { "cdata-sections",
81                      "comments",
82                      "element-content-whitespace",
83                      "namespaces",
84                      "expand-entity-references",
85                      "coalescing",
86                      "validating",
87                      "xinclude-aware",
88                      "entity-resolver",
89                      "error-handler" });
90  
91    private LSParserFilter filter;
92    private final boolean async;
93    private String schemaType;
94    private SAXEventSink eventSink;
95    private SAXParserFactory factory;
96    private XMLReader reader;
97  
98    private boolean namespaceAware = true;
99    private boolean ignoreWhitespace;
100   private boolean expandEntityReferences;
101   private boolean ignoreComments;
102   private boolean coalescing;
103   private boolean validating;
104   private boolean xIncludeAware;
105   private EntityResolver entityResolver;
106   private ErrorHandler errorHandler;
107 
108   public DomLSParser(short mode, String schemaType)
109     throws DOMException
110   {
111     switch (mode)
112       {
113       case DOMImplementationLS.MODE_ASYNCHRONOUS:
114         async = true;
115         break;
116       case DOMImplementationLS.MODE_SYNCHRONOUS:
117         async = false;
118         break;
119       default:
120         throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
121       }
122     // TODO schemaType
123     this.schemaType = schemaType;
124     factory = SAXParserFactory.newInstance();
125   }
126 
127   // -- LSParser --
128   
129   public DOMConfiguration getDomConfig()
130   {
131     return this;
132   }
133   
134   public LSParserFilter getFilter()
135   {
136     return filter;
137   }
138 
139   public void setFilter(LSParserFilter filter)
140   {
141     this.filter = filter;
142   }
143 
144   public boolean getAsync()
145   {
146     return async;
147   }
148 
149   public boolean getBusy()
150   {
151     return eventSink != null;
152   }
153 
154   public Document parse(LSInput input)
155     throws DOMException, LSException
156   {
157     if (async)
158       {
159         return doParse(input);
160       }
161     else
162       {
163         synchronized (this)
164           {
165             return doParse(input);
166           }
167       }
168   }
169 
170   public Document parseURI(String uri)
171     throws DOMException, LSException
172   {
173     LSInput input = new DomLSInput();
174     input.setSystemId(uri);
175     return parse(input);
176   }
177 
178   public Node parseWithContext(LSInput input, Node context, short action)
179     throws DOMException, LSException
180   {
181     Document doc = (context.getNodeType() == Node.DOCUMENT_NODE) ?
182       (Document) context : context.getOwnerDocument();
183     input.setBaseURI(doc.getDocumentURI());
184     // TODO use namespaces defined on context node
185     Document ret = parse(input);
186     Node root = ret.getDocumentElement();
187     root = doc.adoptNode(root);
188     switch (action)
189       {
190       case ACTION_APPEND_AS_CHILDREN:
191         context.appendChild(root);
192         break;
193       case ACTION_REPLACE_CHILDREN:
194         Node c1 = context.getFirstChild();
195         while (c1 != null)
196           {
197             Node next = c1.getNextSibling();
198             context.removeChild(c1);
199             c1 = next;
200           }
201         context.appendChild(root);
202         break;
203       case ACTION_INSERT_BEFORE:
204         Node p1 = context.getParentNode();
205         p1.insertBefore(root, context);
206         break;
207       case ACTION_INSERT_AFTER:
208         Node p2 = context.getParentNode();
209         Node r1 = context.getNextSibling();
210         if (r1 == null)
211           {
212             p2.appendChild(root);
213           }
214         else
215           {
216             p2.insertBefore(root, r1);
217           }
218         break;
219       case ACTION_REPLACE:
220         Node p3 = context.getParentNode();
221         Node r2 = context.getNextSibling();
222         p3.removeChild(context);
223         if (r2 == null)
224           {
225             p3.appendChild(root);
226           }
227         else
228           {
229             p3.insertBefore(root, r2);
230           }
231         break;
232       }
233     return root;
234   }
235 
236   public void abort()
237   {
238     if (eventSink != null)
239       {
240         eventSink.interrupt();
241       }
242   }
243 
244   private Document doParse(LSInput input)
245     throws DOMException, LSException
246   {
247     // create event sink
248     if (eventSink != null)
249       {
250         throw new LSException(LSException.PARSE_ERR, "parse in progress");
251       }
252     InputSource source = getInputSource(input);
253     eventSink = (filter == null) ? new SAXEventSink() :
254       new FilteredSAXEventSink(filter);
255     // configure sink
256     eventSink.namespaceAware = namespaceAware;
257     eventSink.ignoreWhitespace = ignoreWhitespace;
258     eventSink.expandEntityReferences = expandEntityReferences;
259     eventSink.ignoreComments = ignoreComments;
260     eventSink.coalescing = coalescing;
261     // get and configure reader
262     XMLReader reader = getXMLReader();
263     try
264       {
265         reader.setContentHandler(eventSink);
266         reader.setDTDHandler(eventSink);
267         reader.setProperty("http://xml.org/sax/properties/lexical-handler",
268                            eventSink);
269         reader.setProperty("http://xml.org/sax/properties/declaration-handler",
270                            eventSink);
271         reader.setFeature("http://xml.org/sax/features/namespaces",
272                           namespaceAware);
273         reader.setFeature("http://xml.org/sax/features/namespace-prefixes",
274                           true);
275         reader.setFeature("http://xml.org/sax/features/validation",
276                           validating);
277         try
278           {
279             reader.setFeature("http://xml.org/sax/features/use-attributes2",
280                               true);
281           }
282         catch (SAXNotRecognizedException e)
283           {
284             // ignore
285           }
286         try
287           {
288             reader.setFeature("http://xml.org/sax/features/external-general-entities",
289                               true);
290           }
291         catch (SAXNotRecognizedException e)
292           {
293             // ignore
294           }
295         reader.setEntityResolver(entityResolver);
296         reader.setErrorHandler(errorHandler);
297         // parse
298         reader.parse(source);
299       }
300     catch (DOMException e)
301       {
302         reader = null;
303         eventSink = null;
304         throw e;
305       }
306     catch (SAXException e)
307       {
308         reader = null;
309         eventSink = null;
310         throw new DomLSException(LSException.PARSE_ERR, e);
311       }
312     catch (IOException e)
313       {
314         reader = null;
315         eventSink = null;
316         throw new DomLSException(LSException.PARSE_ERR, e);
317       }
318     // return document
319     Document ret = eventSink.doc;
320     String systemId = input.getSystemId();
321     if (systemId != null && ret instanceof DomDocument)
322       {
323         ((DomDocument) ret).setDocumentURI(systemId);
324       }
325     eventSink = null;
326     return ret;
327   }
328 
329   private XMLReader getXMLReader()
330     throws LSException
331   {
332     if (reader == null)
333       {
334         factory.setNamespaceAware(namespaceAware);
335         factory.setValidating(validating);
336         factory.setXIncludeAware(xIncludeAware);
337         try
338           {
339             SAXParser parser = factory.newSAXParser();
340             reader = parser.getXMLReader();
341           }
342         catch (ParserConfigurationException e)
343           {
344             throw new DomLSException(LSException.PARSE_ERR, e);
345           }
346         catch (SAXException e)
347           {
348             throw new DomLSException(LSException.PARSE_ERR, e);
349           }
350       }
351     return reader;
352   }
353 
354   private InputSource getInputSource(LSInput input)
355     throws LSException
356   {
357     InputSource source = null;
358     String systemId = input.getSystemId();
359     InputStream in = input.getByteStream();
360     if (in != null)
361       {
362         source = new InputSource(in);
363         source.setSystemId(systemId);
364       }
365     if (source == null && entityResolver != null)
366       {
367         String publicId = input.getPublicId();
368         try
369           {
370             source = entityResolver.resolveEntity(publicId, systemId);
371           }
372         catch (SAXException e)
373           {
374             throw new DomLSException(LSException.PARSE_ERR, e);
375           } 
376         catch (IOException e)
377           {
378             throw new DomLSException(LSException.PARSE_ERR, e);
379           } 
380       }
381     if (source == null)
382       {
383         URL url = null;
384         String base = input.getBaseURI();
385         try
386           {
387             try
388               {
389                 URL baseURL = (base == null) ? null : new URL(base);
390                 url = (baseURL == null) ? new URL(systemId) :
391                   new URL(baseURL, systemId);
392               }
393             catch (MalformedURLException e)
394               {
395                 File baseFile = (base == null) ? null : new File(base);
396                 url = (baseFile == null) ? new File(systemId).toURL() :
397                   new File(baseFile, systemId).toURL();
398               }
399             in = url.openStream();
400             systemId = url.toString();
401             source = new InputSource(in);
402             source.setSystemId(systemId);
403           }
404         catch (IOException e)
405           {
406             throw new DomLSException(LSException.PARSE_ERR, e);
407           }
408       }
409     return source;
410   }
411 
412   // -- DOMConfiguration --
413 
414   public void setParameter(String name, Object value)
415     throws DOMException
416   {
417     name = name.toLowerCase();
418     if ("cdata-sections".equals(name))
419       {
420         coalescing = !((Boolean) value).booleanValue();
421       }
422     else if ("comments".equals(name))
423       {
424         ignoreComments = !((Boolean) value).booleanValue();
425       }
426     else if ("element-content-whitespace".equals(name))
427       {
428         ignoreWhitespace = !((Boolean) value).booleanValue();
429       }
430     else if ("namespaces".equals(name))
431       {
432         namespaceAware = ((Boolean) value).booleanValue();
433       }
434     else if ("expand-entity-references".equals(name))
435       {
436         expandEntityReferences = ((Boolean) value).booleanValue();
437       }
438     else if ("coalescing".equals(name))
439       {
440         coalescing = ((Boolean) value).booleanValue();
441       }
442     else if ("validating".equals(name))
443       {
444         validating = ((Boolean) value).booleanValue();
445       }
446     else if ("xinclude-aware".equals(name))
447       {
448         xIncludeAware = ((Boolean) value).booleanValue();
449       }
450     else if ("entity-resolver".equals(name))
451       {
452         entityResolver = (EntityResolver) value;
453       }
454     else if ("error-handler".equals(name))
455       {
456         errorHandler = (ErrorHandler) value;
457       }
458     else
459       {
460         throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
461       }
462     // invalidate reader, a new one will be created
463     reader = null;
464   }
465 
466   public Object getParameter(String name)
467     throws DOMException
468   {
469     name = name.toLowerCase();
470     if ("cdata-sections".equals(name))
471       {
472         return coalescing ? Boolean.FALSE : Boolean.TRUE;
473       }
474     else if ("comments".equals(name))
475       {
476         return ignoreComments ? Boolean.FALSE : Boolean.TRUE;
477       }
478     else if ("element-content-whitespace".equals(name))
479       {
480         return ignoreWhitespace ? Boolean.FALSE : Boolean.TRUE;
481       }
482     else if ("namespaces".equals(name))
483       {
484         return namespaceAware ? Boolean.TRUE : Boolean.FALSE;
485       }
486     else if ("expand-entity-references".equals(name))
487       {
488         return expandEntityReferences ? Boolean.TRUE : Boolean.FALSE;
489       }
490     else if ("coalescing".equals(name))
491       {
492         return coalescing ? Boolean.TRUE : Boolean.FALSE;
493       }
494     else if ("validating".equals(name))
495       {
496         return validating ? Boolean.TRUE : Boolean.FALSE;
497       }
498     else if ("xinclude-aware".equals(name))
499       {
500         return xIncludeAware ? Boolean.TRUE : Boolean.FALSE;
501       }
502     else if ("entity-resolver".equals(name))
503       {
504         return entityResolver;
505       }
506     else if ("error-handler".equals(name))
507       {
508         return errorHandler;
509       }
510     else
511       {
512         throw new DomDOMException(DOMException.NOT_SUPPORTED_ERR);
513       }
514   }
515 
516   public boolean canSetParameter(String name, Object value)
517   {
518     return contains(name);
519   }
520 
521   public DOMStringList getParameterNames()
522   {
523     return this;
524   }
525 
526   // -- DOMStringList --
527 
528   public String item(int i)
529   {
530     return (String) SUPPORTED_PARAMETERS.get(i);
531   }
532 
533   public int getLength()
534   {
535     return SUPPORTED_PARAMETERS.size();
536   }
537 
538   public boolean contains(String str)
539   {
540     return SUPPORTED_PARAMETERS.contains(str);
541   }
542 
543   // -- ErrorHandler --
544 
545   public void warning(SAXParseException e)
546     throws SAXException
547   {
548     if (errorHandler != null)
549       {
550         errorHandler.warning(e);
551       }
552   }
553 
554   public void error(SAXParseException e)
555     throws SAXException
556   {
557     if (errorHandler != null)
558       {
559         errorHandler.error(e);
560       }
561   }
562 
563   public void fatalError(SAXParseException e)
564     throws SAXException
565   {
566     if (errorHandler != null)
567       {
568         errorHandler.fatalError(e);
569       }
570     abort();
571   }
572   
573 }
574