KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > emf > ecore > xmi > impl > XMLLoadImpl


1 /**
2  * <copyright>
3  *
4  * Copyright (c) 2002-2004 IBM Corporation and others.
5  * All rights reserved. This program and the accompanying materials
6  * are made available under the terms of the Eclipse Public License v1.0
7  * which accompanies this distribution, and is available at
8  * http://www.eclipse.org/legal/epl-v10.html
9  *
10  * Contributors:
11  * IBM - Initial API and implementation
12  *
13  * </copyright>
14  *
15  * $Id: XMLLoadImpl.java,v 1.8 2005/06/16 04:06:26 marcelop Exp $
16  */

17 package org.eclipse.emf.ecore.xmi.impl;
18
19
20 import java.io.BufferedInputStream JavaDoc;
21 import java.io.IOException JavaDoc;
22 import java.io.InputStream JavaDoc;
23 import java.util.Collections JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import javax.xml.parsers.ParserConfigurationException JavaDoc;
28 import javax.xml.parsers.SAXParser JavaDoc;
29 import javax.xml.parsers.SAXParserFactory JavaDoc;
30
31 import org.w3c.dom.CDATASection JavaDoc;
32 import org.w3c.dom.Comment JavaDoc;
33 import org.w3c.dom.Document JavaDoc;
34 import org.w3c.dom.DocumentType JavaDoc;
35 import org.w3c.dom.Element JavaDoc;
36 import org.w3c.dom.NamedNodeMap JavaDoc;
37 import org.w3c.dom.Node JavaDoc;
38 import org.xml.sax.Attributes JavaDoc;
39 import org.xml.sax.InputSource JavaDoc;
40 import org.xml.sax.SAXException JavaDoc;
41 import org.xml.sax.ext.LexicalHandler JavaDoc;
42 import org.xml.sax.helpers.AttributesImpl JavaDoc;
43 import org.xml.sax.helpers.DefaultHandler JavaDoc;
44
45 import org.eclipse.emf.ecore.resource.Resource;
46 import org.eclipse.emf.ecore.util.ExtendedMetaData;
47 import org.eclipse.emf.ecore.xmi.XMIException;
48 import org.eclipse.emf.ecore.xmi.XMLHelper;
49 import org.eclipse.emf.ecore.xmi.XMLLoad;
50 import org.eclipse.emf.ecore.xmi.XMLParserPool;
51 import org.eclipse.emf.ecore.xmi.XMLResource;
52
53
54 /**
55  * This class begins parsing with the given input stream using the XML
56  * deserializer.
57  */

58 public class XMLLoadImpl implements XMLLoad
59 {
60   protected static final String JavaDoc SAX_LEXICAL_PROPERTY = "http://xml.org/sax/properties/lexical-handler";
61   protected static final int BUFFER_SIZE = 200;
62   protected XMLResource resource;
63   protected InputStream JavaDoc is;
64   protected XMLHelper helper;
65   protected Map JavaDoc options;
66
67   public XMLLoadImpl(XMLHelper helper)
68   {
69     this.helper = helper;
70   }
71
72   /**
73    * Start parsing with the default handler; either XMI
74    * or XML.
75    */

76   public void load(XMLResource resource, InputStream JavaDoc inputStream, Map JavaDoc options) throws IOException JavaDoc
77   {
78     this.resource = resource;
79     is = inputStream;
80     this.options = options;
81     XMLParserPool pool = (XMLParserPool)options.get(XMLResource.OPTION_USE_PARSER_POOL);
82     Map JavaDoc parserFeatures = (Map JavaDoc) options.get(XMLResource.OPTION_PARSER_FEATURES);
83     Map JavaDoc parserProperties = (Map JavaDoc)options.get(XMLResource.OPTION_PARSER_PROPERTIES);
84     parserFeatures = (parserFeatures == null) ? Collections.EMPTY_MAP : parserFeatures;
85     parserProperties = (parserProperties == null) ? Collections.EMPTY_MAP : parserProperties;
86
87     // HACK: reading encoding
88
String JavaDoc encoding = getEncoding();
89     resource.setEncoding(encoding);
90     try
91     {
92       SAXParser JavaDoc parser;
93
94       if (pool != null)
95       {
96         // use the pool to retrieve the parser
97
parser = pool.get(parserFeatures, parserProperties, Boolean.TRUE.equals(options.get(XMLResource.OPTION_USE_LEXICAL_HANDLER)));
98       }
99       else
100       {
101         parser = makeParser();
102         // set features and properties
103
if (parserFeatures != null)
104         {
105           for (Iterator JavaDoc i = parserFeatures.keySet().iterator(); i.hasNext();)
106           {
107             String JavaDoc feature = (String JavaDoc) i.next();
108             parser.getXMLReader().setFeature(feature, ((Boolean JavaDoc) parserFeatures.get(feature)).booleanValue());
109           }
110         }
111         if (parserProperties !=null)
112         {
113           for (Iterator JavaDoc i = parserProperties.keySet().iterator(); i.hasNext();)
114           {
115             String JavaDoc property = (String JavaDoc) i.next();
116             parser.getXMLReader().setProperty(property, parserProperties.get(property));
117           }
118         }
119       }
120
121       InputSource JavaDoc inputSource = new InputSource JavaDoc(is);
122       if (resource.getURI() != null)
123       {
124         String JavaDoc resourceURI = resource.getURI().toString();
125         inputSource.setPublicId(resourceURI);
126         inputSource.setSystemId(resourceURI);
127       }
128
129       DefaultHandler JavaDoc defaultHandler = makeDefaultHandler();
130       
131       // set lexical handler
132
if (options != null && Boolean.TRUE.equals(options.get(XMLResource.OPTION_USE_LEXICAL_HANDLER)))
133       {
134         if (parserProperties == null || parserProperties.get(SAX_LEXICAL_PROPERTY) == null)
135         {
136           parser.setProperty(SAX_LEXICAL_PROPERTY, defaultHandler);
137         }
138       }
139       
140       parser.parse(inputSource, defaultHandler);
141       
142       // avoid memory leak bug #85141
143
if (defaultHandler instanceof SAXWrapper)
144       {
145         ((SAXWrapper)defaultHandler).handler = null;
146       }
147       
148       // release parser back to the pool
149
if (pool != null)
150       {
151         pool.release(parser, parserFeatures, parserProperties, Boolean.TRUE.equals(options.get(XMLResource.OPTION_USE_LEXICAL_HANDLER)));
152       }
153       
154       helper = null;
155       if (!resource.getErrors().isEmpty())
156       {
157         Exception JavaDoc error = (Exception JavaDoc)resource.getErrors().get(0);
158         if (error instanceof XMIException)
159         {
160           XMIException exception = (XMIException)error;
161           if (exception.getWrappedException() != null)
162           {
163             throw new Resource.IOWrappedException(exception.getWrappedException());
164           }
165         }
166         throw new Resource.IOWrappedException(error);
167       }
168     }
169     catch (SAXException JavaDoc exception)
170     {
171       if (exception.getException() != null)
172       {
173         throw new Resource.IOWrappedException(exception.getException());
174       }
175       else
176       {
177         throw new Resource.IOWrappedException(exception);
178       }
179     }
180     catch (ParserConfigurationException JavaDoc exception)
181     {
182       throw new Resource.IOWrappedException(exception);
183     }
184   }
185
186   /**
187    * Make either a validating or non-validating parser;
188    * throw an if one could not be made.
189    */

190   protected SAXParser JavaDoc makeParser() throws ParserConfigurationException JavaDoc, SAXException JavaDoc
191   {
192     SAXParserFactory JavaDoc f = SAXParserFactory.newInstance();
193     return f.newSAXParser();
194   }
195
196   protected DefaultHandler JavaDoc makeDefaultHandler()
197   {
198     return new SAXWrapper(new SAXXMLHandler(resource, helper, options));
199   }
200
201   protected String JavaDoc getEncoding() throws IOException JavaDoc
202   {
203     if (!is.markSupported())
204       is = new BufferedInputStream JavaDoc(is);
205     
206     byte[] buffer = readBuffer();
207     return XMLHandler.getXMLEncoding(buffer);
208   }
209
210   protected byte[] readBuffer() throws IOException JavaDoc
211   {
212     if (is.available() == 0)
213     {
214       return new byte[0];
215     }
216
217     byte[] buffer = new byte[BUFFER_SIZE];
218     is.mark(BUFFER_SIZE);
219     int bytesRead = is.read(buffer, 0, BUFFER_SIZE);
220     int totalBytesRead = bytesRead;
221     
222     while (bytesRead != -1 && (totalBytesRead < BUFFER_SIZE))
223     {
224       bytesRead = is.read(buffer, totalBytesRead, BUFFER_SIZE - totalBytesRead);
225
226       if (bytesRead != -1)
227         totalBytesRead += bytesRead;
228     }
229
230     if (totalBytesRead < BUFFER_SIZE)
231     {
232       byte[] smallerBuffer = new byte[totalBytesRead];
233       System.arraycopy(buffer, 0, smallerBuffer, 0, totalBytesRead);
234       smallerBuffer = buffer;
235     }
236       
237     is.reset();
238     return buffer;
239   }
240
241   /* (non-Javadoc)
242    * @see org.eclipse.emf.ecore.xmi.XMLLoad#load(org.eclipse.emf.ecore.xmi.XMLResource, org.w3c.dom.Node, java.util.Map)
243    */

244   public void load(XMLResource resource, Node JavaDoc node, Map JavaDoc options) throws IOException JavaDoc
245   {
246     this.resource = resource;
247     this.options = options;
248     DefaultHandler JavaDoc handler = makeDefaultHandler();
249     LexicalHandler JavaDoc lexicalHandler = null;
250
251     if (options != null && Boolean.TRUE.equals(options.get(XMLResource.OPTION_USE_LEXICAL_HANDLER)))
252     {
253       lexicalHandler = (LexicalHandler JavaDoc)handler;
254     }
255
256     AttributesProxy attributesProxy = new AttributesProxy();
257     try
258     {
259       short type = node.getNodeType();
260       if (type == Node.ELEMENT_NODE)
261       {
262         handler.startDocument();
263         if (options != null && Boolean.TRUE.equals(options.get(XMLResource.OPTION_DOM_USE_NAMESPACES_IN_SCOPE)))
264         {
265           traverseElement((Element JavaDoc)node, attributesProxy, handler, lexicalHandler);
266         }
267         else
268         {
269           traverse(node, attributesProxy, handler, lexicalHandler);
270         }
271         handler.endDocument();
272       }
273       else
274       {
275         traverse(node, attributesProxy, handler, lexicalHandler);
276       }
277     }
278     catch (SAXException JavaDoc e)
279     {
280       // ignore
281
}
282
283     if (!resource.getErrors().isEmpty())
284     {
285       Exception JavaDoc error = (Exception JavaDoc)resource.getErrors().get(0);
286       if (error instanceof XMIException)
287       {
288         XMIException exception = (XMIException)error;
289         if (exception.getWrappedException() != null)
290         {
291           throw new Resource.IOWrappedException(exception.getWrappedException());
292         }
293       }
294       throw new Resource.IOWrappedException(error);
295     }
296
297     if (handler instanceof SAXWrapper)
298     {
299       ((SAXWrapper)handler).handler = null;
300     }
301     
302     attributesProxy = null;
303     handler = null;
304     lexicalHandler = null;
305     helper = null;
306   }
307   
308   /**
309    * Special case: traversing root element using namespaces in scope
310    */

311   protected void traverseElement(Element JavaDoc element, AttributesProxy attributesProxy, DefaultHandler JavaDoc handler, LexicalHandler JavaDoc lexicalHandler) throws SAXException JavaDoc
312   {
313     // temporary structure to hold node's attributes + namespaces in scope
314
AttributesImpl JavaDoc attrs = new AttributesImpl JavaDoc();
315     
316     // record node's attributes
317
if (element.hasAttributes())
318     {
319       NamedNodeMap JavaDoc attributes = element.getAttributes();
320       for (int i = 0; i < attributes.getLength(); i++)
321       {
322         Node JavaDoc attr = attributes.item(i);
323         String JavaDoc namespaceURI = attr.getNamespaceURI();
324         if (ExtendedMetaData.XMLNS_URI.equals(namespaceURI))
325         {
326           // add non-duplicate namespace declaration
327
if (attrs.getIndex(attr.getNodeName()) < 0)
328           {
329             attrs.addAttribute("", "", attr.getNodeName(), "CDATA", attr.getNodeValue());
330           }
331         }
332         else
333         {
334           attrs.addAttribute(namespaceURI, attr.getLocalName(), attr.getNodeName(), "CDATA", attr.getNodeValue());
335         }
336       }
337     }
338     
339     Node JavaDoc parent = element.getParentNode();
340     // record namespaces in scope
341
while (parent.getNodeType() != Node.DOCUMENT_NODE)
342     {
343       if (parent.hasAttributes())
344       {
345         NamedNodeMap JavaDoc attributes = parent.getAttributes();
346         for (int i = 0; i < attributes.getLength(); i++)
347         {
348           Node JavaDoc attr = attributes.item(i);
349           // add non-duplicate namespace declaration
350
if (ExtendedMetaData.XMLNS_URI.equals(attr.getNamespaceURI()) && attrs.getIndex(attr.getNodeName()) < 0)
351           {
352             attrs.addAttribute("", "", attr.getNodeName(), "CDATA", attr.getNodeValue());
353           }
354         }
355       }
356       parent = parent.getParentNode();
357     }
358
359     // traverse element node
360
String JavaDoc namespaceURI = element.getNamespaceURI();
361     String JavaDoc localName = element.getLocalName();
362     String JavaDoc qname = element.getNodeName();
363     
364     handler.startElement(namespaceURI, localName , qname, attrs);
365     Node JavaDoc child = element.getFirstChild();
366     while (child != null)
367     {
368       traverse(child, attributesProxy, handler, lexicalHandler);
369       child = child.getNextSibling();
370     }
371     handler.endElement(namespaceURI, localName , qname);
372   }
373
374   protected void traverse(Node JavaDoc node, AttributesProxy attributesProxy, DefaultHandler JavaDoc handler, LexicalHandler JavaDoc lexicalHandler) throws SAXException JavaDoc
375   {
376
377     if (node == null)
378     {
379       return;
380     }
381
382     short type = node.getNodeType();
383     switch (type)
384     {
385       case Node.DOCUMENT_NODE:
386       {
387         Document JavaDoc document = (Document JavaDoc)node;
388         handler.startDocument();
389         Node JavaDoc root = document.getDocumentElement();
390         if (lexicalHandler != null)
391         {
392           DocumentType JavaDoc doctype = (DocumentType JavaDoc)document.getDoctype();
393           if (doctype != null)
394           {
395             String JavaDoc publicId = doctype.getPublicId();
396             String JavaDoc systemId = doctype.getSystemId();
397             lexicalHandler.startDTD(root.getNodeName(), publicId, systemId);
398           }
399         }
400         traverse(root, attributesProxy, handler, lexicalHandler);
401         handler.endDocument();
402         break;
403       }
404       case Node.ELEMENT_NODE:
405       {
406         attributesProxy.setAttributes(node.getAttributes());
407         String JavaDoc namespaceURI = node.getNamespaceURI();
408         String JavaDoc localName = node.getLocalName();
409         String JavaDoc qname = node.getNodeName();
410         
411         handler.startElement(namespaceURI, localName, qname, attributesProxy);
412
413         Node JavaDoc child = node.getFirstChild();
414         while (child != null)
415         {
416           traverse(child, attributesProxy, handler, lexicalHandler);
417           child = child.getNextSibling();
418         }
419         handler.endElement(namespaceURI, localName, qname);
420         break;
421       }
422
423       case Node.CDATA_SECTION_NODE:
424       {
425         if (lexicalHandler != null)
426         {
427           lexicalHandler.startCDATA();
428         }
429         char[] chars = ((CDATASection JavaDoc)node).getData().toCharArray();
430         handler.characters(chars, 0, chars.length);
431         if (lexicalHandler != null)
432         {
433           lexicalHandler.endCDATA();
434         }
435         break;
436       }
437       case Node.TEXT_NODE:
438       {
439         char[] chars = node.getNodeValue().toCharArray();
440         handler.characters(chars, 0, chars.length);
441         break;
442       }
443       case Node.COMMENT_NODE:
444       {
445         if (lexicalHandler != null)
446         {
447           char[] chars = ((Comment JavaDoc)node).getData().toCharArray();
448           lexicalHandler.comment(chars, 0, chars.length);
449         }
450       }
451     }
452   }
453
454   protected static final class AttributesProxy implements Attributes JavaDoc
455   {
456     /** DOM attributes. */
457     protected NamedNodeMap JavaDoc attributes;
458
459     /** Sets the DOM attributes. */
460     public void setAttributes(NamedNodeMap JavaDoc attributes)
461     {
462       this.attributes = attributes;
463     }
464
465     public int getLength()
466     {
467       return attributes.getLength();
468     }
469
470     public String JavaDoc getQName(int index)
471     {
472       Node JavaDoc node = attributes.item(index);
473       return (node != null) ? node.getNodeName() : null;
474     }
475
476     public String JavaDoc getURI(int index)
477     {
478       Node JavaDoc node = attributes.item(index);
479       if (node != null)
480       {
481         String JavaDoc namespaceURI = node.getNamespaceURI();
482         if (ExtendedMetaData.XMLNS_URI.equals(namespaceURI))
483         {
484           return "";
485         }
486         return namespaceURI;
487       }
488       return null;
489     }
490
491     public String JavaDoc getLocalName(int index)
492     {
493       Node JavaDoc node = attributes.item(index);
494       if (node != null)
495       {
496         String JavaDoc prefix = node.getPrefix();
497         if (ExtendedMetaData.XMLNS_PREFIX.equals(prefix))
498         {
499           return "";
500         }
501         return node.getLocalName();
502       }
503       return null;
504     }
505
506     public String JavaDoc getType(int i)
507     {
508       return "CDATA";
509     }
510
511     public String JavaDoc getType(String JavaDoc name)
512     {
513       return "CDATA";
514     }
515
516     public String JavaDoc getType(String JavaDoc uri, String JavaDoc localName)
517     {
518       return "CDATA";
519     }
520
521     public String JavaDoc getValue(int i)
522     {
523       Node JavaDoc node = attributes.item(i);
524       return (node != null) ? node.getNodeValue() : null;
525     }
526
527     public String JavaDoc getValue(String JavaDoc name)
528     {
529       Node JavaDoc node = attributes.getNamedItem(name);
530       return (node != null) ? node.getNodeValue() : null;
531     }
532
533     public String JavaDoc getValue(String JavaDoc uri, String JavaDoc localName)
534     {
535       Node JavaDoc node = attributes.getNamedItemNS(uri, localName);
536       return (node != null) ? node.getNodeValue() : null;
537     }
538
539     public int getIndex(String JavaDoc qName)
540     {
541       Node JavaDoc node = attributes.getNamedItem(qName);
542       if (node != null)
543       {
544         for (int i = 0; i < attributes.getLength(); i++)
545         {
546           Node JavaDoc item = attributes.item(i);
547           if (item == node)
548           {
549             return i;
550           }
551         }
552       }
553       return -1;
554     }
555
556     public int getIndex(String JavaDoc uri, String JavaDoc localPart)
557     {
558       Node JavaDoc node = attributes.getNamedItemNS(uri, localPart);
559       if (node != null)
560       {
561         for (int i = 0; i < attributes.getLength(); i++)
562         {
563           Node JavaDoc item = attributes.item(i);
564           if (item == node)
565           {
566             return i;
567           }
568         }
569       }
570       return -1;
571     }
572   } // class AttributesProxy
573

574 } // XMLLoad
575
Popular Tags