1 /*
2 * Copyright 2005-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 }