View Javadoc
1   /*
2    * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4    *
5    * This code is free software; you can redistribute it and/or modify it
6    * under the terms of the GNU General Public License version 2 only, as
7    * published by the Free Software Foundation.  Oracle designates this
8    * particular file as subject to the "Classpath" exception as provided
9    * by Oracle in the LICENSE file that accompanied this code.
10   *
11   * This code is distributed in the hope that it will be useful, but WITHOUT
12   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13   * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14   * version 2 for more details (a copy is included in the LICENSE file that
15   * accompanied this code).
16   *
17   * You should have received a copy of the GNU General Public License version
18   * 2 along with this work; if not, write to the Free Software Foundation,
19   * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20   *
21   * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22   * or visit www.oracle.com if you need additional information or have any
23   * questions.
24   */
25  
26  package com.sun.org.apache.xalan.internal.xsltc.trax;
27  
28  import java.io.IOException;
29  import java.util.Hashtable;
30  import java.util.Stack;
31  import java.util.Vector;
32  import java.util.Iterator;
33  
34  import org.xml.sax.Attributes;
35  import org.xml.sax.ContentHandler;
36  import org.xml.sax.DTDHandler;
37  import org.xml.sax.EntityResolver;
38  import org.xml.sax.ErrorHandler;
39  import org.xml.sax.InputSource;
40  import org.xml.sax.Locator;
41  import org.xml.sax.SAXException;
42  import org.xml.sax.SAXNotRecognizedException;
43  import org.xml.sax.SAXNotSupportedException;
44  import org.xml.sax.XMLReader;
45  import org.xml.sax.ext.LexicalHandler;
46  import org.xml.sax.ext.Locator2;
47  import org.xml.sax.helpers.AttributesImpl;
48  import com.sun.org.apache.xalan.internal.xsltc.dom.SAXImpl;
49  
50  
51  
52  import javax.xml.namespace.QName;
53  import javax.xml.stream.XMLStreamReader;
54  import javax.xml.stream.XMLStreamConstants;
55  import javax.xml.stream.XMLStreamException;
56  import javax.xml.stream.events.Attribute;
57  import javax.xml.stream.events.Characters;
58  import javax.xml.stream.events.EndElement;
59  import javax.xml.stream.events.Namespace;
60  import javax.xml.stream.events.ProcessingInstruction;
61  import javax.xml.stream.events.StartElement;
62  import javax.xml.stream.events.StartDocument;
63  import javax.xml.stream.events.XMLEvent;
64  
65  
66  
67  /**
68   * @author Padmaja Vedula
69   * @author Sunitha Reddy
70   */
71  public class StAXStream2SAX implements XMLReader, Locator {
72  
73      //private final static String EMPTYSTRING = "";
74      //private static final String XMLNS_PREFIX = "xmlns";
75  
76      // StAX Stream source
77      private final XMLStreamReader staxStreamReader;
78  
79      //private Node _dom = null;
80      private ContentHandler _sax = null;
81      private LexicalHandler _lex = null;
82      private SAXImpl _saxImpl = null;
83      //private Hashtable _nsPrefixes = new Hashtable();
84  
85      public StAXStream2SAX(XMLStreamReader staxSrc) {
86              staxStreamReader = staxSrc;
87      }
88  
89      public ContentHandler getContentHandler() {
90          return _sax;
91      }
92  
93      public void setContentHandler(ContentHandler handler) throws
94          NullPointerException
95      {
96          _sax = handler;
97          if (handler instanceof LexicalHandler) {
98              _lex = (LexicalHandler) handler;
99          }
100 
101         if (handler instanceof SAXImpl) {
102             _saxImpl = (SAXImpl)handler;
103         }
104     }
105 
106 
107     public void parse(InputSource unused) throws IOException, SAXException {
108         try {
109             bridge();
110         } catch (XMLStreamException e) {
111             throw new SAXException(e);
112         }
113     }
114 
115 
116     //Main Work Starts Here.
117     public void parse() throws IOException, SAXException, XMLStreamException {
118         bridge();
119     }
120 
121 
122    /**
123      * This class is only used internally so this method should never
124      * be called.
125      */
126     public void parse(String sysId) throws IOException, SAXException {
127         throw new IOException("This method is not yet implemented.");
128     }
129 
130 
131    public void bridge() throws XMLStreamException {
132 
133         try {
134             // remembers the nest level of elements to know when we are done.
135             int depth=0;
136 
137             // skip over START_DOCUMENT
138             int event = staxStreamReader.getEventType();
139             if (event == XMLStreamConstants.START_DOCUMENT) {
140                 event = staxStreamReader.next();
141             }
142 
143             // If not a START_ELEMENT (e.g., a DTD), skip to next tag
144             if (event != XMLStreamConstants.START_ELEMENT) {
145                 event = staxStreamReader.nextTag();
146                 // An error if a START_ELEMENT isn't found now
147                 if (event != XMLStreamConstants.START_ELEMENT) {
148                     throw new IllegalStateException("The current event is " +
149                             "not START_ELEMENT\n but" + event);
150                 }
151             }
152 
153             handleStartDocument();
154 
155             do {
156                 // These are all of the events listed in the javadoc for
157                 // XMLEvent.
158                 // The spec only really describes 11 of them.
159                 switch (event) {
160                     case XMLStreamConstants.START_ELEMENT :
161                         depth++;
162                         handleStartElement();
163                         break;
164                     case XMLStreamConstants.END_ELEMENT :
165                         handleEndElement();
166                         depth--;
167                         break;
168                     case XMLStreamConstants.CHARACTERS :
169                         handleCharacters();
170                         break;
171                     case XMLStreamConstants.ENTITY_REFERENCE :
172                         handleEntityReference();
173                         break;
174                     case XMLStreamConstants.PROCESSING_INSTRUCTION :
175                         handlePI();
176                         break;
177                     case XMLStreamConstants.COMMENT :
178                         handleComment();
179                         break;
180                     case XMLStreamConstants.DTD :
181                         handleDTD();
182                         break;
183                     case XMLStreamConstants.ATTRIBUTE :
184                         handleAttribute();
185                         break;
186                     case XMLStreamConstants.NAMESPACE :
187                         handleNamespace();
188                         break;
189                     case XMLStreamConstants.CDATA :
190                         handleCDATA();
191                         break;
192                     case XMLStreamConstants.ENTITY_DECLARATION :
193                         handleEntityDecl();
194                         break;
195                     case XMLStreamConstants.NOTATION_DECLARATION :
196                         handleNotationDecl();
197                         break;
198                     case XMLStreamConstants.SPACE :
199                         handleSpace();
200                         break;
201                     default :
202                         throw new InternalError("processing event: " + event);
203                 }
204 
205                 event=staxStreamReader.next();
206             } while (depth!=0);
207 
208             handleEndDocument();
209         } catch (SAXException e) {
210             throw new XMLStreamException(e);
211         }
212     }
213 
214     private void handleEndDocument() throws SAXException {
215         _sax.endDocument();
216     }
217 
218     private void handleStartDocument() throws SAXException {
219         _sax.setDocumentLocator(new Locator2() {
220             public int getColumnNumber() {
221                 return staxStreamReader.getLocation().getColumnNumber();
222             }
223             public int getLineNumber() {
224                 return staxStreamReader.getLocation().getLineNumber();
225             }
226             public String getPublicId() {
227                 return staxStreamReader.getLocation().getPublicId();
228             }
229             public String getSystemId() {
230                 return staxStreamReader.getLocation().getSystemId();
231             }
232             public String getXMLVersion() {
233                 return staxStreamReader.getVersion();
234             }
235             public String getEncoding() {
236                 return staxStreamReader.getEncoding();
237             }
238          });
239         _sax.startDocument();
240     }
241 
242     private void handlePI() throws XMLStreamException {
243         try {
244             _sax.processingInstruction(
245                 staxStreamReader.getPITarget(),
246                 staxStreamReader.getPIData());
247         } catch (SAXException e) {
248             throw new XMLStreamException(e);
249         }
250     }
251 
252     private void handleCharacters() throws XMLStreamException {
253 
254         // workaround for bugid 5046319 - switch over to commented section
255         // below when it is fixed.
256         int textLength = staxStreamReader.getTextLength();
257         char[] chars = new char[textLength];
258 
259         staxStreamReader.getTextCharacters(0, chars, 0, textLength);
260 
261         try {
262             _sax.characters(chars, 0, chars.length);
263         } catch (SAXException e) {
264             throw new XMLStreamException(e);
265         }
266 
267 
268 //        int start = 0;
269 //        int len;
270 //        do {
271 //            len = staxStreamReader.getTextCharacters(start, buf, 0, buf.length);
272 //            start += len;
273 //            try {
274 //                _sax.characters(buf, 0, len);
275 //            } catch (SAXException e) {
276 //                throw new XMLStreamException(e);
277 //            }
278 //        } while (len == buf.length);
279     }
280 
281     private void handleEndElement() throws XMLStreamException {
282         QName qName = staxStreamReader.getName();
283 
284         try {
285             //construct prefix:localName from qName
286             String qname = "";
287             if (qName.getPrefix() != null && qName.getPrefix().trim().length() != 0){
288                 qname = qName.getPrefix() + ":";
289             }
290             qname += qName.getLocalPart();
291 
292             // fire endElement
293             _sax.endElement(
294                 qName.getNamespaceURI(),
295                 qName.getLocalPart(),
296                 qname);
297 
298             // end namespace bindings
299             int nsCount = staxStreamReader.getNamespaceCount();
300             for (int i = nsCount - 1; i >= 0; i--) {
301                 String prefix = staxStreamReader.getNamespacePrefix(i);
302                 if (prefix == null) { // true for default namespace
303                     prefix = "";
304                 }
305                 _sax.endPrefixMapping(prefix);
306             }
307         } catch (SAXException e) {
308             throw new XMLStreamException(e);
309         }
310     }
311 
312     private void handleStartElement() throws XMLStreamException {
313 
314         try {
315             // start namespace bindings
316             int nsCount = staxStreamReader.getNamespaceCount();
317             for (int i = 0; i < nsCount; i++) {
318                 String prefix = staxStreamReader.getNamespacePrefix(i);
319                 if (prefix == null) { // true for default namespace
320                     prefix = "";
321                 }
322                 _sax.startPrefixMapping(
323                     prefix,
324                     staxStreamReader.getNamespaceURI(i));
325             }
326 
327             // fire startElement
328             QName qName = staxStreamReader.getName();
329             String prefix = qName.getPrefix();
330             String rawname;
331             if(prefix==null || prefix.length()==0)
332                 rawname = qName.getLocalPart();
333             else
334                 rawname = prefix + ':' + qName.getLocalPart();
335             Attributes attrs = getAttributes();
336             _sax.startElement(
337                 qName.getNamespaceURI(),
338                 qName.getLocalPart(),
339                 rawname,
340                 attrs);
341         } catch (SAXException e) {
342             throw new XMLStreamException(e);
343         }
344     }
345 
346     /**
347      * Get the attributes associated with the given START_ELEMENT or ATTRIBUTE
348      * StAXevent.
349      *
350      * @return the StAX attributes converted to an org.xml.sax.Attributes
351      */
352     private Attributes getAttributes() {
353         AttributesImpl attrs = new AttributesImpl();
354 
355         int eventType = staxStreamReader.getEventType();
356         if (eventType != XMLStreamConstants.ATTRIBUTE
357             && eventType != XMLStreamConstants.START_ELEMENT) {
358             throw new InternalError(
359                 "getAttributes() attempting to process: " + eventType);
360         }
361 
362         // in SAX, namespace declarations are not part of attributes by default.
363         // (there's a property to control that, but as far as we are concerned
364         // we don't use it.) So don't add xmlns:* to attributes.
365 
366         // gather non-namespace attrs
367         for (int i = 0; i < staxStreamReader.getAttributeCount(); i++) {
368             String uri = staxStreamReader.getAttributeNamespace(i);
369             if(uri==null)   uri="";
370             String localName = staxStreamReader.getAttributeLocalName(i);
371             String prefix = staxStreamReader.getAttributePrefix(i);
372             String qName;
373             if(prefix==null || prefix.length()==0)
374                 qName = localName;
375             else
376                 qName = prefix + ':' + localName;
377             String type = staxStreamReader.getAttributeType(i);
378             String value = staxStreamReader.getAttributeValue(i);
379 
380             attrs.addAttribute(uri, localName, qName, type, value);
381         }
382 
383         return attrs;
384     }
385 
386     private void handleNamespace() {
387         // no-op ???
388         // namespace events don't normally occur outside of a startElement
389         // or endElement
390     }
391 
392     private void handleAttribute() {
393         // no-op ???
394         // attribute events don't normally occur outside of a startElement
395         // or endElement
396     }
397 
398     private void handleDTD() {
399         // no-op ???
400         // it seems like we need to pass this info along, but how?
401     }
402 
403     private void handleComment() {
404         // no-op ???
405     }
406 
407     private void handleEntityReference() {
408         // no-op ???
409     }
410 
411     private void handleSpace() {
412         // no-op ???
413         // this event is listed in the javadoc, but not in the spec.
414     }
415 
416     private void handleNotationDecl() {
417         // no-op ???
418         // this event is listed in the javadoc, but not in the spec.
419     }
420 
421     private void handleEntityDecl() {
422         // no-op ???
423         // this event is listed in the javadoc, but not in the spec.
424     }
425 
426     private void handleCDATA() {
427         // no-op ???
428         // this event is listed in the javadoc, but not in the spec.
429     }
430 
431 
432     /**
433      * This class is only used internally so this method should never
434      * be called.
435      */
436     public DTDHandler getDTDHandler() {
437         return null;
438     }
439 
440     /**
441      * This class is only used internally so this method should never
442      * be called.
443      */
444     public ErrorHandler getErrorHandler() {
445         return null;
446     }
447 
448     /**
449      * This class is only used internally so this method should never
450      * be called.
451      */
452     public boolean getFeature(String name) throws SAXNotRecognizedException,
453         SAXNotSupportedException
454     {
455         return false;
456     }
457 
458     /**
459      * This class is only used internally so this method should never
460      * be called.
461      */
462     public void setFeature(String name, boolean value) throws
463         SAXNotRecognizedException, SAXNotSupportedException
464     {
465     }
466 
467     /**
468      * This class is only used internally so this method should never
469      * be called.
470      */
471     public void setDTDHandler(DTDHandler handler) throws NullPointerException {
472     }
473 
474     /**
475      * This class is only used internally so this method should never
476      * be called.
477      */
478     public void setEntityResolver(EntityResolver resolver) throws
479         NullPointerException
480     {
481     }
482 
483     /**
484      * This class is only used internally so this method should never
485      * be called.
486      */
487     public EntityResolver getEntityResolver() {
488         return null;
489     }
490 
491     /**
492      * This class is only used internally so this method should never
493      * be called.
494      */
495     public void setErrorHandler(ErrorHandler handler) throws
496         NullPointerException
497     {
498     }
499 
500     /**
501      * This class is only used internally so this method should never
502      * be called.
503      */
504     public void setProperty(String name, Object value) throws
505         SAXNotRecognizedException, SAXNotSupportedException {
506     }
507 
508     /**
509      * This class is only used internally so this method should never
510      * be called.
511      */
512     public Object getProperty(String name) throws SAXNotRecognizedException,
513         SAXNotSupportedException
514     {
515         return null;
516     }
517 
518     /**
519      * This class is only used internally so this method should never
520      * be called.
521      */
522     public int getColumnNumber() {
523         return 0;
524     }
525 
526     /**
527      * This class is only used internally so this method should never
528      * be called.
529      */
530     public int getLineNumber() {
531         return 0;
532     }
533 
534     /**
535      * This class is only used internally so this method should never
536      * be called.
537      */
538     public String getPublicId() {
539         return null;
540     }
541 
542     /**
543      * This class is only used internally so this method should never
544      * be called.
545      */
546     public String getSystemId() {
547         return null;
548     }
549 
550 }