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