View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership.  The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License.  You may obtain a copy of the License at
9    *
10   *   http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied.  See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.myfaces.view.facelets.compiler;
20  
21  import java.io.BufferedInputStream;
22  import java.io.IOException;
23  import java.io.InputStream;
24  import java.net.URL;
25  import java.util.regex.Matcher;
26  import java.util.regex.Pattern;
27  import java.security.AccessController;
28  import java.security.PrivilegedExceptionAction;
29  import java.security.PrivilegedActionException;
30  
31  import javax.el.ELException;
32  import javax.faces.FacesException;
33  import javax.faces.view.Location;
34  import javax.faces.view.facelets.FaceletException;
35  import javax.faces.view.facelets.FaceletHandler;
36  import javax.faces.view.facelets.Tag;
37  import javax.faces.view.facelets.TagAttribute;
38  import javax.faces.view.facelets.TagAttributes;
39  import javax.xml.parsers.ParserConfigurationException;
40  import javax.xml.parsers.SAXParser;
41  import javax.xml.parsers.SAXParserFactory;
42  
43  import org.apache.myfaces.shared.util.ClassUtils;
44  import org.apache.myfaces.view.facelets.tag.TagAttributeImpl;
45  import org.apache.myfaces.view.facelets.tag.TagAttributesImpl;
46  import org.apache.myfaces.view.facelets.tag.composite.CompositeLibrary;
47  import org.apache.myfaces.view.facelets.tag.composite.ImplementationHandler;
48  import org.apache.myfaces.view.facelets.tag.composite.InterfaceHandler;
49  import org.apache.myfaces.view.facelets.tag.jsf.core.CoreLibrary;
50  import org.xml.sax.Attributes;
51  import org.xml.sax.InputSource;
52  import org.xml.sax.Locator;
53  import org.xml.sax.SAXException;
54  import org.xml.sax.SAXParseException;
55  import org.xml.sax.XMLReader;
56  import org.xml.sax.ext.LexicalHandler;
57  import org.xml.sax.helpers.DefaultHandler;
58  
59  /**
60   * Compiler implementation that uses SAX
61   * 
62   * @see org.apache.myfaces.view.facelets.compiler.Compiler
63   * 
64   * @author Jacob Hookom
65   * @version $Id: SAXCompiler.java 1526421 2013-09-26 08:57:11Z lu4242 $
66   */
67  public final class SAXCompiler extends Compiler
68  {
69  
70      private final static Pattern XmlDeclaration = Pattern
71              .compile("^<\\?xml.+?version=['\"](.+?)['\"](.+?encoding=['\"]((.+?))['\"])?.*?\\?>");
72  
73      private static class CompilationHandler extends DefaultHandler implements LexicalHandler
74      {
75  
76          private final String alias;
77  
78          private boolean inDocument = false;
79  
80          private Locator locator;
81  
82          private final CompilationManager unit;
83  
84          public CompilationHandler(CompilationManager unit, String alias)
85          {
86              this.unit = unit;
87              this.alias = alias;
88          }
89  
90          public void characters(char[] ch, int start, int length) throws SAXException
91          {
92              if (this.inDocument)
93              {
94                  this.unit.writeText(new String(ch, start, length));
95              }
96          }
97  
98          public void comment(char[] ch, int start, int length) throws SAXException
99          {
100             if (this.inDocument)
101             {
102                 this.unit.writeComment(new String(ch, start, length));
103             }
104         }
105 
106         protected TagAttributes createAttributes(Attributes attrs)
107         {
108             int len = attrs.getLength();
109             TagAttribute[] ta = new TagAttribute[len];
110             for (int i = 0; i < len; i++)
111             {
112                 ta[i] = new TagAttributeImpl(this.createLocation(), attrs.getURI(i), attrs.getLocalName(i), attrs
113                         .getQName(i), attrs.getValue(i));
114             }
115             return new TagAttributesImpl(ta);
116         }
117 
118         protected Location createLocation()
119         {
120             return new Location(this.alias, this.locator.getLineNumber(), this.locator.getColumnNumber());
121         }
122 
123         public void endCDATA() throws SAXException
124         {
125             if (this.inDocument)
126             {
127                 this.unit.writeInstruction("]]>");
128             }
129         }
130 
131         public void endDocument() throws SAXException
132         {
133             super.endDocument();
134         }
135 
136         public void endDTD() throws SAXException
137         {
138             this.inDocument = true;
139         }
140 
141         public void endElement(String uri, String localName, String qName) throws SAXException
142         {
143             this.unit.popTag();
144         }
145 
146         public void endEntity(String name) throws SAXException
147         {
148         }
149 
150         public void endPrefixMapping(String prefix) throws SAXException
151         {
152             this.unit.popNamespace(prefix);
153         }
154 
155         public void fatalError(SAXParseException e) throws SAXException
156         {
157             if (this.locator != null)
158             {
159                 throw new SAXException("Error Traced[line: " + this.locator.getLineNumber() + "] " + e.getMessage());
160             }
161             else
162             {
163                 throw e;
164             }
165         }
166 
167         public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
168         {
169             if (this.inDocument)
170             {
171                 this.unit.writeWhitespace(new String(ch, start, length));
172             }
173         }
174 
175         public InputSource resolveEntity(String publicId, String systemId) throws SAXException
176         {
177             String dtd = "org/apache/myfaces/resource/default.dtd";
178             /*
179              * if ("-//W3C//DTD XHTML 1.0 Transitional//EN".equals(publicId)) { dtd = "xhtml1-transitional.dtd"; } else
180              * if (systemId != null && systemId.startsWith("file:/")) { return new InputSource(systemId); }
181              */
182             URL url = ClassUtils.getResource(dtd);
183             return new InputSource(url.toString());
184         }
185 
186         public void setDocumentLocator(Locator locator)
187         {
188             this.locator = locator;
189         }
190 
191         public void startCDATA() throws SAXException
192         {
193             if (this.inDocument)
194             {
195                 this.unit.writeInstruction("<![CDATA[");
196             }
197         }
198 
199         public void startDocument() throws SAXException
200         {
201             this.inDocument = true;
202         }
203 
204         public void startDTD(String name, String publicId, String systemId) throws SAXException
205         {
206             if (this.inDocument)
207             {
208                 StringBuffer sb = new StringBuffer(64);
209                 sb.append("<!DOCTYPE ").append(name);
210                 if (publicId != null)
211                 {
212                     sb.append(" PUBLIC \"").append(publicId).append("\"");
213                     if (systemId != null)
214                     {
215                         sb.append(" \"").append(systemId).append("\"");
216                     }
217                 }
218                 else if (systemId != null)
219                 {
220                     sb.append(" SYSTEM \"").append(systemId).append("\"");
221                 }
222                 sb.append(" >\n");
223                 this.unit.writeInstruction(sb.toString());
224             }
225             this.inDocument = false;
226         }
227 
228         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
229         {
230             this.unit.pushTag(new Tag(this.createLocation(), uri, localName, qName, this.createAttributes(attributes)));
231         }
232 
233         public void startEntity(String name) throws SAXException
234         {
235         }
236 
237         public void startPrefixMapping(String prefix, String uri) throws SAXException
238         {
239             this.unit.pushNamespace(prefix, uri);
240         }
241 
242         public void processingInstruction(String target, String data) throws SAXException
243         {
244             if (this.inDocument)
245             {
246                 StringBuffer sb = new StringBuffer(64);
247                 sb.append("<?").append(target).append(' ').append(data).append("?>\n");
248                 this.unit.writeInstruction(sb.toString());
249             }
250         }
251     }
252     
253     /**
254      * Like CompilationHandler but does not take into account everything outside f:metadata tag 
255      * 
256      * @since 2.0
257      */
258     private static class ViewMetadataHandler extends DefaultHandler implements LexicalHandler
259     {
260 
261         private final String alias;
262 
263         private boolean inDocument = false;
264 
265         private Locator locator;
266 
267         private final CompilationManager unit;
268         
269         private boolean inMetadata = false;
270 
271         public ViewMetadataHandler(CompilationManager unit, String alias)
272         {
273             this.unit = unit;
274             this.alias = alias;
275         }
276 
277         public void characters(char[] ch, int start, int length) throws SAXException
278         {
279             if (this.inDocument && inMetadata)
280             {
281                 this.unit.writeText(new String(ch, start, length));
282             }
283         }
284 
285         public void comment(char[] ch, int start, int length) throws SAXException
286         {
287             if (this.inDocument && inMetadata)
288             {
289                 this.unit.writeComment(new String(ch, start, length));
290             }
291         }
292 
293         protected TagAttributes createAttributes(Attributes attrs)
294         {
295             int len = attrs.getLength();
296             TagAttribute[] ta = new TagAttribute[len];
297             for (int i = 0; i < len; i++)
298             {
299                 ta[i] = new TagAttributeImpl(this.createLocation(), attrs.getURI(i), attrs.getLocalName(i), attrs
300                         .getQName(i), attrs.getValue(i));
301             }
302             return new TagAttributesImpl(ta);
303         }
304 
305         protected Location createLocation()
306         {
307             return new Location(this.alias, this.locator.getLineNumber(), this.locator.getColumnNumber());
308         }
309 
310         public void endCDATA() throws SAXException
311         {
312             if (this.inDocument && inMetadata)
313             {
314                 this.unit.writeInstruction("]]>");
315             }
316         }
317 
318         public void endDocument() throws SAXException
319         {
320             super.endDocument();
321         }
322 
323         public void endDTD() throws SAXException
324         {
325             this.inDocument = true;
326         }
327 
328         public void endElement(String uri, String localName, String qName) throws SAXException
329         {
330             if (inMetadata)
331             {
332                 this.unit.popTag();
333             }
334             if ( CoreLibrary.Namespace.equals(uri) )
335             {
336                 if ("metadata".equals(localName))
337                 {
338                     this.inMetadata=false;
339                 }
340                 else if (!inMetadata && "view".equals(localName))
341                 {
342                     this.unit.popTag();
343                 }
344             }
345         }
346 
347         public void endEntity(String name) throws SAXException
348         {
349         }
350 
351         public void endPrefixMapping(String prefix) throws SAXException
352         {
353             this.unit.popNamespace(prefix);
354         }
355 
356         public void fatalError(SAXParseException e) throws SAXException
357         {
358             if (this.locator != null)
359             {
360                 throw new SAXException("Error Traced[line: " + this.locator.getLineNumber() + "] " + e.getMessage());
361             }
362             else
363             {
364                 throw e;
365             }
366         }
367 
368         public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
369         {
370             if (this.inDocument && inMetadata)
371             {
372                 this.unit.writeWhitespace(new String(ch, start, length));
373             }
374         }
375 
376         public InputSource resolveEntity(String publicId, String systemId) throws SAXException
377         {
378             String dtd = "org/apache/myfaces/resource/default.dtd";
379             /*
380              * if ("-//W3C//DTD XHTML 1.0 Transitional//EN".equals(publicId)) { dtd = "xhtml1-transitional.dtd"; } else
381              * if (systemId != null && systemId.startsWith("file:/")) { return new InputSource(systemId); }
382              */
383             URL url = ClassUtils.getResource(dtd);
384             return new InputSource(url.toString());
385         }
386 
387         public void setDocumentLocator(Locator locator)
388         {
389             this.locator = locator;
390         }
391 
392         public void startCDATA() throws SAXException
393         {
394             if (this.inDocument && inMetadata)
395             {
396                 this.unit.writeInstruction("<![CDATA[");
397             }
398         }
399 
400         public void startDocument() throws SAXException
401         {
402             this.inDocument = true;
403         }
404 
405         public void startDTD(String name, String publicId, String systemId) throws SAXException
406         {
407             // metadata does not require output doctype
408             this.inDocument = false;
409         }
410 
411         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
412         {
413             if ( CoreLibrary.Namespace.equals(uri) )
414             {
415                 if ("metadata".equals(localName))
416                 {
417                     this.inMetadata=true;
418                 }
419                 else if (!inMetadata && "view".equals(localName))
420                 {
421                     this.unit.pushTag(new Tag(this.createLocation(), uri, localName, qName, this.createAttributes(attributes)));
422                 }
423             }
424             if (inMetadata)
425             {
426                 this.unit.pushTag(new Tag(this.createLocation(), uri, localName, qName, this.createAttributes(attributes)));
427             }
428         }
429 
430         public void startEntity(String name) throws SAXException
431         {
432         }
433 
434         public void startPrefixMapping(String prefix, String uri) throws SAXException
435         {
436             this.unit.pushNamespace(prefix, uri);
437         }
438 
439         public void processingInstruction(String target, String data) throws SAXException
440         {
441             if (this.inDocument && inMetadata)
442             {
443                 StringBuffer sb = new StringBuffer(64);
444                 sb.append("<?").append(target).append(' ').append(data).append("?>\n");
445                 this.unit.writeInstruction(sb.toString());
446             }
447         }        
448     }
449     
450     /**
451      * Like CompilationHandler but does not take into account everything outside cc:interface or cc:implementation tag.
452      *  
453      * Note inside cc:implementation it only takes into account cc:insertChildren, cc:insertFacet and cc:renderFacet,
454      * all other tags, comments or text are just skipped.
455      * 
456      * @since 2.0.1
457      */
458     private static class CompositeComponentMetadataHandler extends DefaultHandler implements LexicalHandler
459     {
460 
461         private final String alias;
462 
463         private boolean inDocument = false;
464 
465         private Locator locator;
466 
467         private final CompilationManager unit;
468         
469         private boolean inCompositeInterface = false;
470         
471         private boolean inCompositeImplementation = false;
472 
473         public CompositeComponentMetadataHandler(CompilationManager unit, String alias)
474         {
475             this.unit = unit;
476             this.alias = alias;
477         }
478 
479         public void characters(char[] ch, int start, int length) throws SAXException
480         {
481             if (this.inDocument && inCompositeInterface)
482             {
483                 this.unit.writeText(new String(ch, start, length));
484             }
485         }
486 
487         public void comment(char[] ch, int start, int length) throws SAXException
488         {
489             if (this.inDocument && inCompositeInterface)
490             {
491                 this.unit.writeComment(new String(ch, start, length));
492             }
493         }
494 
495         protected TagAttributes createAttributes(Attributes attrs)
496         {
497             int len = attrs.getLength();
498             TagAttribute[] ta = new TagAttribute[len];
499             for (int i = 0; i < len; i++)
500             {
501                 ta[i] = new TagAttributeImpl(this.createLocation(), attrs.getURI(i), attrs.getLocalName(i), attrs
502                         .getQName(i), attrs.getValue(i));
503             }
504             return new TagAttributesImpl(ta);
505         }
506 
507         protected Location createLocation()
508         {
509             return new Location(this.alias, this.locator.getLineNumber(), this.locator.getColumnNumber());
510         }
511 
512         public void endCDATA() throws SAXException
513         {
514             if (this.inDocument && inCompositeInterface)
515             {
516                 this.unit.writeInstruction("]]>");
517             }
518         }
519 
520         public void endDocument() throws SAXException
521         {
522             super.endDocument();
523         }
524 
525         public void endDTD() throws SAXException
526         {
527             this.inDocument = true;
528         }
529 
530         public void endElement(String uri, String localName, String qName) throws SAXException
531         {
532             if (inCompositeInterface)
533             {
534                 this.unit.popTag();
535             }
536             else if (inCompositeImplementation && CompositeLibrary.NAMESPACE.equals(uri))
537             {
538                 if ( "insertFacet".equals(localName) ||
539                      "renderFacet".equals(localName) ||
540                      "insertChildren".equals(localName) || 
541                      ImplementationHandler.NAME.equals(localName))
542                 {
543                     this.unit.popTag();
544                 }
545             }
546             
547             if (CompositeLibrary.NAMESPACE.equals(uri))
548             {
549                 if (InterfaceHandler.NAME.equals(localName))
550                 {
551                     this.inCompositeInterface=false;
552                 }
553                 else if (ImplementationHandler.NAME.equals(localName))
554                 {
555                     this.inCompositeImplementation=false;
556                 }
557             }
558         }
559 
560         public void endEntity(String name) throws SAXException
561         {
562         }
563 
564         public void endPrefixMapping(String prefix) throws SAXException
565         {
566             this.unit.popNamespace(prefix);
567         }
568 
569         public void fatalError(SAXParseException e) throws SAXException
570         {
571             if (this.locator != null)
572             {
573                 throw new SAXException("Error Traced[line: " + this.locator.getLineNumber() + "] " + e.getMessage());
574             }
575             else
576             {
577                 throw e;
578             }
579         }
580 
581         public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
582         {
583             if (this.inDocument && inCompositeInterface)
584             {
585                 this.unit.writeWhitespace(new String(ch, start, length));
586             }
587         }
588 
589         public InputSource resolveEntity(String publicId, String systemId) throws SAXException
590         {
591             String dtd = "org/apache/myfaces/resource/default.dtd";
592             /*
593              * if ("-//W3C//DTD XHTML 1.0 Transitional//EN".equals(publicId)) { dtd = "xhtml1-transitional.dtd"; } else
594              * if (systemId != null && systemId.startsWith("file:/")) { return new InputSource(systemId); }
595              */
596             URL url = ClassUtils.getResource(dtd);
597             return new InputSource(url.toString());
598         }
599 
600         public void setDocumentLocator(Locator locator)
601         {
602             this.locator = locator;
603         }
604 
605         public void startCDATA() throws SAXException
606         {
607             if (this.inDocument && inCompositeInterface)
608             {
609                 this.unit.writeInstruction("<![CDATA[");
610             }
611         }
612 
613         public void startDocument() throws SAXException
614         {
615             this.inDocument = true;
616         }
617 
618         public void startDTD(String name, String publicId, String systemId) throws SAXException
619         {
620             // metadata does not require output doctype
621             this.inDocument = false;
622         }
623 
624         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
625         {
626             if (CompositeLibrary.NAMESPACE.equals(uri))
627             {
628                 if (InterfaceHandler.NAME.equals(localName))
629                 {
630                     this.inCompositeInterface=true;
631                 }
632                 else if (ImplementationHandler.NAME.equals(localName))
633                 {
634                     this.inCompositeImplementation=true;
635                 }
636             }
637             
638             if (inCompositeInterface)
639             {
640                 this.unit.pushTag(new Tag(this.createLocation(), uri, localName, qName, this.createAttributes(attributes)));
641             }
642             else if (inCompositeImplementation && CompositeLibrary.NAMESPACE.equals(uri))
643             {
644                 if ("insertFacet".equals(localName)    ||
645                     "renderFacet".equals(localName)    ||
646                     "insertChildren".equals(localName) ||
647                     ImplementationHandler.NAME.equals(localName)   )
648                 {
649                     this.unit.pushTag(new Tag(this.createLocation(), uri, localName, qName, this.createAttributes(attributes)));
650                 }
651             }
652         }
653 
654         public void startEntity(String name) throws SAXException
655         {
656         }
657 
658         public void startPrefixMapping(String prefix, String uri) throws SAXException
659         {
660             this.unit.pushNamespace(prefix, uri);
661         }
662 
663         public void processingInstruction(String target, String data) throws SAXException
664         {
665             if (this.inDocument && inCompositeInterface)
666             {
667                 StringBuffer sb = new StringBuffer(64);
668                 sb.append("<?").append(target).append(' ').append(data).append("?>\n");
669                 this.unit.writeInstruction(sb.toString());
670             }
671         }        
672     }
673 
674     public SAXCompiler()
675     {
676         super();
677     }
678 
679     public FaceletHandler doCompile(URL src, String alias) throws IOException, FaceletException, ELException,
680             FacesException
681     {
682         CompilationManager mngr = null;
683         InputStream is = null;
684         String encoding = null;
685         try
686         {
687             is = new BufferedInputStream(src.openStream(), 1024);
688             mngr = new CompilationManager(alias, this);
689             encoding = writeXmlDecl(is, mngr);
690             CompilationHandler handler = new CompilationHandler(mngr, alias);
691             SAXParser parser = this.createSAXParser(handler);
692             parser.parse(is, handler);
693         }
694         catch (SAXException e)
695         {
696             throw new FaceletException("Error Parsing " + alias + ": " + e.getMessage(), e.getCause());
697         }
698         catch (ParserConfigurationException e)
699         {
700             throw new FaceletException("Error Configuring Parser " + alias + ": " + e.getMessage(), e.getCause());
701         }
702         finally
703         {
704             if (is != null)
705             {
706                 is.close();
707             }
708         }
709         return new EncodingHandler(mngr.createFaceletHandler(), encoding);
710     }
711 
712     /**
713      * @since 2.0
714      */
715     @Override
716     protected FaceletHandler doCompileViewMetadata(URL src, String alias)
717             throws IOException, FaceletException, ELException, FacesException
718     {
719         CompilationManager mngr = null;
720         InputStream is = null;
721         String encoding = null;
722         try
723         {
724             is = new BufferedInputStream(src.openStream(), 1024);
725             mngr = new CompilationManager(alias, this);
726             encoding = getXmlDecl(is, mngr);
727             final ViewMetadataHandler handler = new ViewMetadataHandler(mngr, alias);
728             final SAXParser parser = this.createSAXParser(handler);
729             
730             if (System.getSecurityManager() != null)
731             {
732                 try
733                 {
734                     final InputStream finalInputStream = is;
735                     AccessController.doPrivileged(new PrivilegedExceptionAction() 
736                     {
737                         public Object run() throws SAXException, IOException 
738                         {
739                             parser.parse(finalInputStream, handler);
740                             return null; 
741                         }
742                     });
743                 }
744                 catch (PrivilegedActionException pae)
745                 {
746                     Exception e = pae.getException();
747                     if(e instanceof SAXException)
748                     {
749                         throw new FaceletException("Error Parsing " + alias + ": " + e.getMessage(), e.getCause());
750                     } 
751                     else if(e instanceof IOException)
752                     {
753                         throw (IOException)e;
754                     }
755                 }
756             }
757             else
758             {
759                 parser.parse(is, handler);
760             }
761         }
762         catch (SAXException e)
763         {
764             throw new FaceletException("Error Parsing " + alias + ": " + e.getMessage(), e.getCause());
765         }
766         catch (ParserConfigurationException e)
767         {
768             throw new FaceletException("Error Configuring Parser " + alias + ": " + e.getMessage(), e.getCause());
769         }
770         finally
771         {
772             if (is != null)
773             {
774                 is.close();
775             }
776         }
777         return new EncodingHandler(mngr.createFaceletHandler(), encoding);
778     }
779 
780     /**
781      * @since 2.0.1
782      */
783     @Override
784     protected FaceletHandler doCompileCompositeComponentMetadata(URL src, String alias)
785             throws IOException, FaceletException, ELException, FacesException
786     {
787         CompilationManager mngr = null;
788         InputStream is = null;
789         String encoding = null;
790         try
791         {
792             is = new BufferedInputStream(src.openStream(), 1024);
793             mngr = new CompilationManager(alias, this);
794             encoding = getXmlDecl(is, mngr);
795             CompositeComponentMetadataHandler handler = new CompositeComponentMetadataHandler(mngr, alias);
796             SAXParser parser = this.createSAXParser(handler);
797             parser.parse(is, handler);
798         }
799         catch (SAXException e)
800         {
801             throw new FaceletException("Error Parsing " + alias + ": " + e.getMessage(), e.getCause());
802         }
803         catch (ParserConfigurationException e)
804         {
805             throw new FaceletException("Error Configuring Parser " + alias + ": " + e.getMessage(), e.getCause());
806         }
807         finally
808         {
809             if (is != null)
810             {
811                 is.close();
812             }
813         }
814         return new EncodingHandler(mngr.createFaceletHandler(), encoding);
815     }
816 
817     protected static final String writeXmlDecl(InputStream is, CompilationManager mngr) throws IOException
818     {
819         is.mark(128);
820         String encoding = null;
821         try
822         {
823             byte[] b = new byte[128];
824             if (is.read(b) > 0)
825             {
826                 String r = new String(b);
827                 Matcher m = XmlDeclaration.matcher(r);
828                 if (m.find())
829                 {
830                     mngr.writeInstruction(m.group(0) + "\n");
831                     if (m.group(3) != null)
832                     {
833                         encoding = m.group(3);
834                     }
835                 }
836             }
837         }
838         finally
839         {
840             is.reset();
841         }
842         return encoding;
843     }
844     
845     protected static final String getXmlDecl(InputStream is, CompilationManager mngr) throws IOException
846     {
847         is.mark(128);
848         String encoding = null;
849         try
850         {
851             byte[] b = new byte[128];
852             if (is.read(b) > 0)
853             {
854                 String r = new String(b);
855                 Matcher m = XmlDeclaration.matcher(r);
856                 if (m.find())
857                 {
858                     //mngr.writeInstruction(m.group(0) + "\n");
859                     if (m.group(3) != null)
860                     {
861                         encoding = m.group(3);
862                     }
863                 }
864             }
865         }
866         finally
867         {
868             is.reset();
869         }
870         return encoding;
871     }
872 
873     private final SAXParser createSAXParser(DefaultHandler handler) throws SAXException,
874             ParserConfigurationException
875     {
876         SAXParserFactory factory = SAXParserFactory.newInstance();
877         factory.setNamespaceAware(true);
878         factory.setFeature("http://xml.org/sax/features/namespace-prefixes", true);
879         factory.setFeature("http://xml.org/sax/features/validation", this.isValidating());
880         factory.setValidating(this.isValidating());
881         SAXParser parser = factory.newSAXParser();
882         XMLReader reader = parser.getXMLReader();
883         reader.setProperty("http://xml.org/sax/properties/lexical-handler", handler);
884         reader.setErrorHandler(handler);
885         reader.setEntityResolver(handler);
886         return parser;
887     }
888 
889 }