KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > quercus > lib > xml > XmlReader


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  * Free SoftwareFoundation, Inc.
23  * 59 Temple Place, Suite 330
24  * Boston, MA 02111-1307 USA
25  *
26  * @author Scott Ferguson
27  */

28
29 package com.caucho.quercus.lib.xml;
30
31 import com.caucho.quercus.annotation.Optional;
32 import com.caucho.quercus.env.BooleanValue;
33 import com.caucho.quercus.env.Env;
34 import com.caucho.quercus.env.LongValue;
35 import com.caucho.quercus.env.NullValue;
36 import com.caucho.quercus.env.StringValue;
37 import com.caucho.quercus.env.Value;
38 import com.caucho.util.L10N;
39 import com.caucho.vfs.Path;
40
41 import javax.xml.stream.*;
42 import java.io.IOException JavaDoc;
43 import java.util.HashMap JavaDoc;
44 import java.util.logging.Level JavaDoc;
45 import java.util.logging.Logger JavaDoc;
46
47 public class XmlReader
48 {
49   private static final Logger JavaDoc log
50     = Logger.getLogger(XmlReader.class.getName());
51   private static final L10N L = new L10N(XmlReader.class);
52
53   private int _depth;
54   private int _lastNodeType;
55   private int _lastNonTextNode;
56
57   private int _currentNodeType;
58
59   private boolean _hasAttribute;
60
61   private XMLStreamReader _streamReader;
62
63   private static final HashMap JavaDoc<Integer JavaDoc, Integer JavaDoc> _constConvertMap
64     = new HashMap JavaDoc<Integer JavaDoc, Integer JavaDoc>();
65
66   private HashMap JavaDoc<String JavaDoc, Integer JavaDoc> _startElements;
67
68   public static final int NONE = 0;
69   public static final int ELEMENT = 1;
70   public static final int ATTRIBUTE = 2;
71   public static final int TEXT = 3;
72   public static final int CDATA = 4;
73   public static final int ENTITY_REF = 5;
74   public static final int ENTITY = 6;
75   public static final int PI = 7;
76   public static final int COMMENT = 8;
77   public static final int DOC = 9;
78   public static final int DOC_TYPE = 10;
79   public static final int DOC_FRAGMENT = 11;
80   public static final int NOTATION = 12;
81   public static final int WHITESPACE = 13;
82   public static final int SIGNIFICANT_WHITESPACE = 14;
83   public static final int END_ELEMENT = 15;
84   public static final int END_ENTITY = 16;
85   public static final int XML_DECLARATION = 17;
86
87   public static final int LOADDTD = 1;
88   public static final int DEFAULTATTRS = 2;
89   public static final int VALIDATE = 3;
90   public static final int SUBST_ENTITIES = 4;
91
92   /**
93    * Default constructor.
94    *
95    * XXX: Not completely sure what the passed in string(s) does.
96    *
97    * @param string not used
98    */

99   public XmlReader(@Optional String JavaDoc[] string) {
100     _depth = 0;
101     _lastNodeType = -1;
102     _currentNodeType = XMLStreamConstants.START_DOCUMENT;
103
104     _streamReader = null;
105
106     _startElements = new HashMap JavaDoc<String JavaDoc, Integer JavaDoc>();
107
108     _hasAttribute = false;
109   }
110
111   /**
112    * Determines if the stream has been opened and produces a warning if not.
113    *
114    * @param env
115    * @param operation name of the operation being performed (i.e. read, etc.)
116    * @return true if the stream is open, false otherwise
117    */

118   private boolean streamIsOpen(Env env, String JavaDoc operation) {
119     if (! streamIsOpen()) {
120       env.warning(L.l("Load Data before trying to " + operation));
121
122       return false;
123     }
124
125     return true;
126   }
127
128   /**
129    * Determines if the stream has been opened.
130    *
131    * @return true if the stream is open, false otherwise
132    */

133   private boolean streamIsOpen() {
134      return _streamReader != null;
135    }
136
137   /**
138    * Returns the number of attributes of the current element.
139    *
140    * @return the count if it exists, otherwise null
141    */

142   public Value getAttributeCount() {
143     if (! streamIsOpen())
144       return NullValue.NULL;
145
146     try {
147             if (_currentNodeType == XMLStreamConstants.CHARACTERS)
148                     return LongValue.create(0);
149
150       return LongValue.create(_streamReader.getAttributeCount());
151     }
152     catch (IllegalStateException JavaDoc ex) {
153       log.log(Level.WARNING, ex.toString(), ex);
154
155       return NullValue.NULL;
156     }
157   }
158
159   /**
160    * Returns the base uniform resource locator of the current element.
161    *
162    * @return the URI, otherwise null
163    */

164   public Value getBaseURI() {
165     if (! streamIsOpen())
166       return NullValue.NULL;
167
168     // XXX: Not sure how to do this one. StreamReaderImpl.getLocation() is
169
// unsupported and Location.getLocationURI() doesn't exist either though
170
// it's in the web documentation.
171

172     // return StringValue.create(_streamReader.getLocation().getLocationURI());
173

174     return NullValue.NULL;
175   }
176
177   /**
178    * Returns the depth of the current element.
179    *
180    * @return the depth if it exists, otherwise null
181    */

182   public Value getDepth() {
183     if (! streamIsOpen())
184       return NullValue.NULL;
185
186     return LongValue.create(_depth);
187   }
188
189   /**
190    * Determines whether this element has attributes.
191    *
192    * @return true if this element has attributes, false if not, otherwise null
193    */

194   public Value getHasAttributes() {
195     if (! streamIsOpen())
196       return NullValue.NULL;
197
198     try {
199             if (_currentNodeType == XMLStreamConstants.CHARACTERS)
200                     return BooleanValue.FALSE;
201
202       return BooleanValue.create(_hasAttribute || _streamReader.getAttributeCount() > 0);
203     }
204     catch (IllegalStateException JavaDoc ex) {
205       log.log(Level.WARNING, ex.toString(), ex);
206
207       return NullValue.NULL;
208     }
209   }
210
211   /**
212    * Determines whether this element has content.
213    *
214    * @return true if this element has content, false if not, otherwise null
215    */

216   public Value getHasValue() {
217     if (! streamIsOpen())
218       return NullValue.NULL;
219
220     return BooleanValue.create(_streamReader.hasText());
221   }
222
223   /**
224    * Determines whether this element is default.
225    *
226    * @return true if this element is default, false if not, otherwise null
227    */

228   public Value getIsDefault() {
229     if (! streamIsOpen())
230       return NullValue.NULL;
231
232     // XXX: StreamReaderImpl.isAttributeSpecified() only checks for
233
// attribute existence. This should be tested against the atttribute list
234
// but couldn't find anything like that in StreamReader.
235
return BooleanValue.FALSE;
236   }
237
238   /**
239    * Determines whether this element is empty.
240    *
241    * @return true if this element is empty, false if not, otherwise null
242    */

243   public Value getIsEmptyElement() {
244     if (! streamIsOpen())
245       return NullValue.NULL;
246
247     // XXX: The only case I found for isEmptyElement was for something
248
// like <element/>. Even something like <element></element> was
249
// not considered empty. Currently, <element/> is being returned as
250
// <element></element> so it can't be tested properly.
251
return BooleanValue.FALSE;
252   }
253
254   /**
255    * Determines whether this element has attributes.
256    *
257    * @return true if this element has attributes, false if not, otherwise null
258    */

259   public Value getLocalName() {
260     if (! streamIsOpen())
261       return NullValue.NULL;
262
263     String JavaDoc name = "";
264
265           if (_currentNodeType == XMLStreamConstants.CHARACTERS)
266                   name = "#text";
267           else if (_currentNodeType == XMLStreamConstants.COMMENT)
268                   name = "#comment";
269           else
270                   name = _streamReader.getLocalName();
271
272     return StringValue.create(name);
273   }
274
275   /**
276    * Returns the name of the current element.
277    *
278    * @return the name, otherwise null
279    */

280   public Value getName(Env env) {
281     if (! streamIsOpen())
282       return NullValue.NULL;
283
284     try {
285             String JavaDoc name = "";
286
287             // XXX: Next line should be "String prefix = _streamReader.getPrefix();"
288
// but there was a NullPointerException for XMLStreamReaderImpl._name.
289

290             String JavaDoc prefix = null; // _streamReader.getPrefix();
291

292             if (_currentNodeType == XMLStreamConstants.CHARACTERS)
293                     name = "#text";
294             else if (_currentNodeType == XMLStreamConstants.COMMENT)
295                     name = "#comment";
296             else {
297                     if (prefix == null)
298                             name = _streamReader.getName().toString();
299                     else
300                             name = prefix + ":" + _streamReader.getLocalName().toString();
301             }
302
303       return StringValue.create(name);
304     }
305     catch (IllegalStateException JavaDoc ex) {
306       log.log(Level.WARNING, ex.toString(), ex);
307
308       return NullValue.NULL;
309     }
310   }
311
312   /**
313    * Returns the namespace uniform resource locator of the current element.
314    *
315    * @return the namespace URI, otherwise null
316    */

317   public Value getNamespaceURI() {
318     if (! streamIsOpen())
319       return NullValue.NULL;
320
321     return StringValue.create(_streamReader.getNamespaceURI());
322   }
323
324   /**
325    * Returns the node type of the current element.
326    *
327    * @return the node type, otherwise null
328    */

329   public Value getNodeType() {
330           if (! streamIsOpen())
331                   return NullValue.NULL;
332
333           /*
334            Integer convertedInteger = _constConvertMap.get(_nextType);
335
336            int convertedInt = convertedInteger.intValue();
337
338            return LongValue.create(convertedInt);*/

339
340           int convertedInt = SIGNIFICANT_WHITESPACE;
341
342           if (! _streamReader.isWhiteSpace()) {
343                   Integer JavaDoc convertedInteger =
344                   _constConvertMap.get(_streamReader.getEventType());
345
346                   convertedInt = convertedInteger.intValue();
347           }
348
349           return LongValue.create(convertedInt);
350   }
351
352   /**
353    * Returns the prefix of the current element.
354    *
355    * @return the prefix, otherwise null
356    */

357   public Value getPrefix() {
358     if (! streamIsOpen())
359       return NullValue.NULL;
360
361     return StringValue.create(_streamReader.getPrefix());
362   }
363
364   /**
365    * Returns the value of the current element.
366    *
367    * @return the value, otherwise null
368    */

369   public Value getValue() {
370     if (! streamIsOpen())
371       return NullValue.NULL;
372
373     // XXX: This is returning an end of line along with the text when
374
// it probably should be only the text.
375

376     if (_currentNodeType != XMLStreamConstants.END_ELEMENT)
377             return StringValue.create(_streamReader.getText());
378
379     return StringValue.create(null);
380   }
381
382   /**
383    * Returns the node type of the current element.
384    *
385    * @return the node type, otherwise null
386    */

387   public Value getXmlLang() {
388     if (! streamIsOpen())
389       return NullValue.NULL;
390
391     // XXX: Defaulted for now.
392
return StringValue.create("");
393   }
394
395   /**
396    * Closes the reader.
397    *
398    * @return true if success, false otherwise
399    */

400   public BooleanValue close() {
401     if (! streamIsOpen())
402       return BooleanValue.TRUE;
403
404     try {
405       _streamReader.close();
406     }
407     catch (XMLStreamException ex) {
408       log.log(Level.WARNING, ex.toString(), ex);
409
410       return BooleanValue.FALSE;
411     }
412
413     return BooleanValue.TRUE;
414   }
415
416   /**
417    *
418    * @return
419    */

420   public Value expand() {
421     throw new UnsupportedOperationException JavaDoc(getClass().getName());
422   }
423
424   /**
425    *
426    * @param name
427    * @return
428    */

429   public StringValue getAttribute(String JavaDoc name) {
430     throw new UnsupportedOperationException JavaDoc(getClass().getName());
431   }
432
433   /**
434    *
435    * @param index
436    * @return
437    */

438   public StringValue getAttributeNo(int index) {
439     throw new UnsupportedOperationException JavaDoc(getClass().getName());
440   }
441
442   /**
443    *
444    * @param localName
445    * @param namespaceURI
446    * @return
447    */

448   public StringValue getAttributeNS(String JavaDoc localName, String JavaDoc namespaceURI) {
449     throw new UnsupportedOperationException JavaDoc(getClass().getName());
450   }
451
452   /**
453    *
454    * @param property
455    * @return
456    */

457   public BooleanValue getParserProperty(int property) {
458     throw new UnsupportedOperationException JavaDoc(getClass().getName());
459   }
460
461   /**
462    *
463    * @return
464    */

465   public BooleanValue isValid() {
466     throw new UnsupportedOperationException JavaDoc(getClass().getName());
467   }
468
469   /**
470    *
471    * @param prefix
472    * @return
473    */

474   public BooleanValue lookupNamespace(String JavaDoc prefix) {
475     throw new UnsupportedOperationException JavaDoc(getClass().getName());
476   }
477
478   /**
479    *
480    * @param name
481    * @return
482    */

483   public BooleanValue moveToAttribute(String JavaDoc name) {
484     throw new UnsupportedOperationException JavaDoc(getClass().getName());
485   }
486
487   /**
488    *
489    * @param index
490    * @return
491    */

492   public BooleanValue moveToAttributeNo(int index) {
493     throw new UnsupportedOperationException JavaDoc(getClass().getName());
494   }
495
496   /**
497    *
498    * @param localName
499    * @param namespaceURI
500    * @return
501    */

502   public BooleanValue moveToAttributeNs(String JavaDoc localName, String JavaDoc namespaceURI) {
503     throw new UnsupportedOperationException JavaDoc(getClass().getName());
504   }
505
506   /**
507    *
508    * @return
509    */

510   public BooleanValue moveToElement() {
511     throw new UnsupportedOperationException JavaDoc(getClass().getName());
512   }
513
514   /**
515    *
516    * @return
517    */

518   public BooleanValue moveToFirstAttribute() {
519     throw new UnsupportedOperationException JavaDoc(getClass().getName());
520   }
521
522   /**
523    *
524    * @return
525    */

526   public BooleanValue moveToNextAttribute() {
527     throw new UnsupportedOperationException JavaDoc(getClass().getName());
528   }
529
530   /**
531    *
532    * @param localname
533    * @return
534    */

535   public BooleanValue next(@Optional String JavaDoc localname) {
536     throw new UnsupportedOperationException JavaDoc(getClass().getName());
537   }
538
539   /**
540    * Opens a stream using the uniform resource locator.
541    *
542    * @param uri uniform resource locator to open
543    * @return true if success, false otherwise
544    */

545   public BooleanValue open(Env env, Path path) {
546     try {
547       XMLInputFactory factory = XMLInputFactory.newInstance();
548     
549       _streamReader = factory.createXMLStreamReader(path.openRead());
550     }
551     catch (XMLStreamException ex) {
552       log.log(Level.WARNING, ex.toString(), ex);
553
554       env.warning(L.l("Unable to open source data"));
555
556       return BooleanValue.FALSE;
557     }
558     catch (IOException JavaDoc ex) {
559       log.log(Level.WARNING, ex.toString(), ex);
560
561       env.warning(L.l("Unable to open source data"));
562
563       return BooleanValue.FALSE;
564     }
565
566     return BooleanValue.TRUE;
567   }
568
569   /**
570    * Records the last node type.
571    *
572    */

573   private void updateLastNode() {
574     _lastNodeType = _currentNodeType;
575
576     if (_currentNodeType != XMLStreamConstants.CHARACTERS &&
577         _currentNodeType != XMLStreamConstants.COMMENT)
578             _lastNonTextNode = _currentNodeType;
579   }
580
581   /**
582    * Updates the depth.
583    *
584    */

585   private void updateDepth(Env env) {
586     if (_lastNodeType == XMLStreamConstants.START_ELEMENT &&
587         ! _streamReader.isEndElement())
588       _depth++;
589     else if ((_lastNodeType == XMLStreamConstants.CHARACTERS ||
590               _lastNodeType == XMLStreamConstants.COMMENT) &&
591                                                            _currentNodeType == XMLStreamConstants.END_ELEMENT)
592             _depth--;
593   }
594
595   /**
596    * Maintains the _hasAttribute variable.
597    *
598    */

599   private void updateAttribute(Env env) {
600           _hasAttribute = false;
601
602           String JavaDoc key = getName(env).toString() + _depth;
603
604            if (_currentNodeType == XMLStreamConstants.START_ELEMENT &&
605                _streamReader.getAttributeCount() > 0) {
606                            _startElements.put(key, _depth);
607
608                            _hasAttribute = true;
609                    }
610
611            if (_currentNodeType == XMLStreamConstants.END_ELEMENT &&
612                _startElements.containsKey(key)) {
613                                    _hasAttribute = true;
614
615                                    _startElements.remove(key);
616           }
617   }
618
619   /**
620    * Moves the cursor to the next node.
621    *
622    * @return true if success, false otherwise
623    */

624   public BooleanValue read(Env env) {
625     if (! streamIsOpen(env, "read"))
626       return BooleanValue.FALSE;
627
628     try {
629       if (! _streamReader.hasNext())
630         return BooleanValue.FALSE;
631
632       updateLastNode();
633
634       _currentNodeType = _streamReader.next();
635
636       if (_currentNodeType == XMLStreamConstants.SPACE)
637               return read(env);
638
639       if (_currentNodeType == XMLStreamConstants.END_DOCUMENT)
640               return BooleanValue.FALSE;
641
642       updateDepth(env);
643
644       updateAttribute(env);
645
646     }
647     catch (XMLStreamException ex) {
648       log.log(Level.WARNING, ex.toString(), ex);
649
650       env.warning(L.l("Unable to read :" + ex.toString()));
651
652       return BooleanValue.FALSE;
653     }
654
655     return BooleanValue.TRUE;
656   }
657
658   public LongValue getNextType() {
659     return LongValue.create(_currentNodeType);
660   }
661
662   /**
663    *
664    * @param property
665    * @param value
666    * @return
667    */

668   public BooleanValue setParserProperty(int property, boolean value) {
669     throw new UnsupportedOperationException JavaDoc(getClass().getName());
670   }
671
672   /**
673    *
674    * @param filename
675    * @return
676    */

677   public BooleanValue setRelaxNGSchema(String JavaDoc filename) {
678     throw new UnsupportedOperationException JavaDoc(getClass().getName());
679   }
680
681   /**
682    *
683    * @param source
684    * @return
685    */

686   public BooleanValue setRelaxNGSchemaSource(String JavaDoc source) {
687     throw new UnsupportedOperationException JavaDoc(getClass().getName());
688   }
689
690   /**
691    *
692    * @param source
693    * @return
694    */

695   public BooleanValue XML(String JavaDoc source) {
696     throw new UnsupportedOperationException JavaDoc(getClass().getName());
697   }
698
699   static {
700           _constConvertMap.put(XMLStreamConstants.ATTRIBUTE,
701                                ATTRIBUTE);
702           _constConvertMap.put(XMLStreamConstants.CDATA,
703                                CDATA);
704           _constConvertMap.put(XMLStreamConstants.CHARACTERS,
705                                TEXT);
706           _constConvertMap.put(XMLStreamConstants.COMMENT,
707                                COMMENT);
708           _constConvertMap.put(XMLStreamConstants.END_ELEMENT,
709                                END_ELEMENT);
710         /*
711     _constConvertMap.put(XMLStreamConstants.END_ENTITY,
712             END_ENTITY);
713         */

714           // XXX: XMLStreamConstants.ENTITY_DECLARATION is 17 in the BAE docs
715
// but is 15 in the Resin implementation.
716
_constConvertMap.put(XMLStreamConstants.ENTITY_DECLARATION,
717                                ENTITY); // ENTITY used twice
718
_constConvertMap.put(XMLStreamConstants.ENTITY_REFERENCE,
719                                ENTITY_REF);
720           _constConvertMap.put(XMLStreamConstants.NOTATION_DECLARATION,
721                                NOTATION);
722           _constConvertMap.put(XMLStreamConstants.PROCESSING_INSTRUCTION,
723                                PI);
724           _constConvertMap.put(XMLStreamConstants.SPACE,
725                                WHITESPACE);
726           _constConvertMap.put(XMLStreamConstants.START_ELEMENT,
727                                ELEMENT);
728         /*
729     _constConvertMap.put(XMLStreamConstants.START_ENTITY,
730             ENTITY);
731         */

732           // Following constants did not match
733
_constConvertMap.put(XMLStreamConstants.DTD, NONE);
734           _constConvertMap.put(XMLStreamConstants.END_DOCUMENT, NONE);
735           _constConvertMap.put(XMLStreamConstants.NAMESPACE, NONE);
736           _constConvertMap.put(XMLStreamConstants.START_DOCUMENT, NONE);
737           _constConvertMap.put(0, NONE); // Pre-Read
738
_constConvertMap.put(-1, NONE);
739           _constConvertMap.put(-1, DOC);
740           _constConvertMap.put(-1, DOC_TYPE);
741           _constConvertMap.put(-1, DOC_FRAGMENT);
742           _constConvertMap.put(-1, DOC_TYPE);
743           _constConvertMap.put(-1, XML_DECLARATION);
744   }
745 }
746
Popular Tags