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 org.apache.myfaces.config.ConfigFilesXmlValidationUtils;
22  import org.apache.myfaces.shared.config.MyfacesConfig;
23  import org.apache.myfaces.shared.util.ArrayUtils;
24  import org.apache.myfaces.shared.util.ClassUtils;
25  import org.apache.myfaces.shared.util.StringUtils;
26  import org.apache.myfaces.shared.util.WebConfigParamUtils;
27  import org.apache.myfaces.spi.FaceletConfigResourceProvider;
28  import org.apache.myfaces.spi.FaceletConfigResourceProviderFactory;
29  import org.apache.myfaces.view.facelets.tag.AbstractTagLibrary;
30  import org.apache.myfaces.view.facelets.tag.TagLibrary;
31  import org.apache.myfaces.view.facelets.tag.composite.CompositeComponentResourceTagHandler;
32  import org.apache.myfaces.view.facelets.tag.composite.CompositeResouceWrapper;
33  import org.apache.myfaces.view.facelets.util.ParameterCheck;
34  import org.apache.myfaces.view.facelets.util.ReflectionUtil;
35  import org.xml.sax.Attributes;
36  import org.xml.sax.InputSource;
37  import org.xml.sax.Locator;
38  import org.xml.sax.SAXException;
39  import org.xml.sax.SAXParseException;
40  import org.xml.sax.XMLReader;
41  import org.xml.sax.helpers.DefaultHandler;
42  
43  import javax.faces.FacesException;
44  import javax.faces.application.Resource;
45  import javax.faces.application.ResourceHandler;
46  import javax.faces.application.ViewHandler;
47  import javax.faces.context.ExternalContext;
48  import javax.faces.context.FacesContext;
49  import javax.faces.view.facelets.ComponentConfig;
50  import javax.faces.view.facelets.FaceletHandler;
51  import javax.faces.view.facelets.Tag;
52  import javax.faces.view.facelets.TagConfig;
53  import javax.faces.view.facelets.TagHandler;
54  import javax.xml.parsers.ParserConfigurationException;
55  import javax.xml.parsers.SAXParser;
56  import javax.xml.parsers.SAXParserFactory;
57  import java.io.IOException;
58  import java.io.InputStream;
59  import java.lang.reflect.Method;
60  import java.net.URL;
61  import java.net.URLConnection;
62  import java.util.Collection;
63  import java.util.logging.Level;
64  import java.util.logging.Logger;
65  import java.util.regex.Pattern;
66  
67  /**
68   * Handles creating a {@link org.apache.myfaces.view.facelets.tag.TagLibrary TagLibrary}
69   * from a {@link java.net.URL URL} source.
70   * 
71   * @author Jacob Hookom
72   * @version $Id: TagLibraryConfig.java 1723396 2016-01-06 18:12:46Z wtlucy $
73   */
74  public final class TagLibraryConfig
75  {
76  
77      //private final static String SUFFIX = ".taglib.xml";
78  
79      //protected final static Logger log = Logger.getLogger("facelets.compiler");
80      protected final static Logger log = Logger.getLogger(TagLibraryConfig.class.getName());
81  
82      private static class TagLibraryImpl extends AbstractTagLibrary
83      {
84          private String _compositeLibraryName;
85          
86          private final ResourceHandler _resourceHandler;
87          private Pattern _acceptPatterns;
88          private String _extension;
89          private String[] _defaultSuffixesArray;
90          
91          public TagLibraryImpl(FacesContext facesContext, String namespace)
92          {
93              super(namespace);
94              _compositeLibraryName = null;
95              _resourceHandler = facesContext.getApplication().getResourceHandler();
96              ExternalContext externalContext = facesContext.getExternalContext();
97              
98              _acceptPatterns = loadAcceptPattern(externalContext);
99  
100             _extension = loadFaceletExtension(externalContext);
101             
102             String defaultSuffixes = WebConfigParamUtils.getStringInitParameter(externalContext,
103                     ViewHandler.DEFAULT_SUFFIX_PARAM_NAME, ViewHandler.DEFAULT_SUFFIX );
104             
105             _defaultSuffixesArray = StringUtils.splitShortString(defaultSuffixes, ' ');
106             
107             boolean faceletsExtensionFound = false;
108             for (String ext : _defaultSuffixesArray)
109             {
110                 if (_extension.equals(ext))
111                 {
112                     faceletsExtensionFound = true;
113                     break;
114                 }
115             }
116             if (!faceletsExtensionFound)
117             {
118                 _defaultSuffixesArray = (String[]) ArrayUtils.concat(_defaultSuffixesArray, new String[]{_extension});
119             }
120         }
121         
122         /**
123          * Load and compile a regular expression pattern built from the Facelet view mapping parameters.
124          * 
125          * @param context
126          *            the application's external context
127          * 
128          * @return the compiled regular expression
129          */
130         private Pattern loadAcceptPattern(ExternalContext context)
131         {
132             assert context != null;
133 
134             String mappings = context.getInitParameter(ViewHandler.FACELETS_VIEW_MAPPINGS_PARAM_NAME);
135             if (mappings == null)
136             {
137                 return null;
138             }
139 
140             // Make sure the mappings contain something
141             mappings = mappings.trim();
142             if (mappings.length() == 0)
143             {
144                 return null;
145             }
146 
147             return Pattern.compile(toRegex(mappings));
148         }
149 
150         private String loadFaceletExtension(ExternalContext context)
151         {
152             assert context != null;
153 
154             String suffix = context.getInitParameter(ViewHandler.FACELETS_SUFFIX_PARAM_NAME);
155             if (suffix == null)
156             {
157                 suffix = ViewHandler.DEFAULT_FACELETS_SUFFIX;
158             }
159             else
160             {
161                 suffix = suffix.trim();
162                 if (suffix.length() == 0)
163                 {
164                     suffix = ViewHandler.DEFAULT_FACELETS_SUFFIX;
165                 }
166             }
167 
168             return suffix;
169         }
170         
171         /**
172          * Convert the specified mapping string to an equivalent regular expression.
173          * 
174          * @param mappings
175          *            le mapping string
176          * 
177          * @return an uncompiled regular expression representing the mappings
178          */
179         private String toRegex(String mappings)
180         {
181             assert mappings != null;
182 
183             // Get rid of spaces
184             mappings = mappings.replaceAll("\\s", "");
185 
186             // Escape '.'
187             mappings = mappings.replaceAll("\\.", "\\\\.");
188 
189             // Change '*' to '.*' to represent any match
190             mappings = mappings.replaceAll("\\*", ".*");
191 
192             // Split the mappings by changing ';' to '|'
193             mappings = mappings.replaceAll(";", "|");
194 
195             return mappings;
196         }
197         
198         public boolean handles(String resourceName)
199         {
200             if (resourceName == null)
201             {
202                 return false;
203             }
204             // Check extension first as it's faster than mappings
205             if (resourceName.endsWith(_extension))
206             {
207                 // If the extension matches, it's a Facelet viewId.
208                 return true;
209             }
210 
211             // Otherwise, try to match the view identifier with the facelet mappings
212             return _acceptPatterns != null && _acceptPatterns.matcher(resourceName).matches();
213         }
214         
215         @Override
216         public boolean containsTagHandler(String ns, String localName)
217         {
218             boolean result = super.containsTagHandler(ns, localName);
219             
220             if (!result && _compositeLibraryName != null && containsNamespace(ns))
221             {
222                 for (String defaultSuffix : _defaultSuffixesArray)
223                 {
224                     String resourceName = localName + defaultSuffix;
225                     if (handles(resourceName))
226                     {
227                         Resource compositeComponentResource = _resourceHandler.createResource(
228                                 resourceName, _compositeLibraryName);
229                         
230                         if (compositeComponentResource != null)
231                         {
232                             URL url = compositeComponentResource.getURL();
233                             return (url != null);
234                         }
235                     }
236                 }
237             }
238             return result;
239         }
240         
241         @Override
242         public TagHandler createTagHandler(String ns, String localName,
243                 TagConfig tag) throws FacesException
244         {
245             TagHandler tagHandler = super.createTagHandler(ns, localName, tag);
246             
247             if (tagHandler == null && _compositeLibraryName != null && containsNamespace(ns))
248             {
249                 for (String defaultSuffix : _defaultSuffixesArray)
250                 {
251                     String resourceName = localName + defaultSuffix;
252                     if (handles(resourceName))
253                     {
254                         // MYFACES-3308 If a composite component exists, it requires to 
255                         // be always resolved. In other words, it should always exists a default.
256                         // The call here for resourceHandler.createResource, just try to get
257                         // the Resource and if it does not exists, it just returns null.
258                         // The intention of this code is just create an instance and pass to
259                         // CompositeComponentResourceTagHandler. Then, its values 
260                         // (resourceName, libraryName) will be used to derive the real instance
261                         // to use in a view, based on the locale used.
262                         Resource compositeComponentResource = new CompositeResouceWrapper(
263                             _resourceHandler.createResource(resourceName, _compositeLibraryName));
264                         
265                         if (compositeComponentResource != null)
266                         {
267                             ComponentConfig componentConfig = new ComponentConfigWrapper(tag,
268                                     "javax.faces.NamingContainer", null);
269                             
270                             return new CompositeComponentResourceTagHandler(
271                                     componentConfig, compositeComponentResource);
272                         }
273                     }
274                 }
275             }
276             return tagHandler;
277         }
278 
279         public void setCompositeLibrary(String compositeLibraryName)
280         {
281             _compositeLibraryName = compositeLibraryName;
282         }
283 
284         public void putConverter(String name, String id)
285         {
286             ParameterCheck.notNull("name", name);
287             ParameterCheck.notNull("id", id);
288             this.addConverter(name, id);
289         }
290 
291         public void putConverter(String name, String id, Class<? extends TagHandler> handlerClass)
292         {
293             ParameterCheck.notNull("name", name);
294             ParameterCheck.notNull("id", id);
295             ParameterCheck.notNull("handlerClass", handlerClass);
296             this.addConverter(name, id, handlerClass);
297         }
298 
299         public void putValidator(String name, String id)
300         {
301             ParameterCheck.notNull("name", name);
302             ParameterCheck.notNull("id", id);
303             this.addValidator(name, id);
304         }
305 
306         public void putValidator(String name, String id, Class<? extends TagHandler> handlerClass)
307         {
308             ParameterCheck.notNull("name", name);
309             ParameterCheck.notNull("id", id);
310             ParameterCheck.notNull("handlerClass", handlerClass);
311             this.addValidator(name, id, handlerClass);
312         }
313 
314         public void putTagHandler(String name, Class<? extends TagHandler> type)
315         {
316             ParameterCheck.notNull("name", name);
317             ParameterCheck.notNull("type", type);
318             this.addTagHandler(name, type);
319         }
320 
321         public void putComponent(String name, String componentType, String rendererType)
322         {
323             ParameterCheck.notNull("name", name);
324             ParameterCheck.notNull("componentType", componentType);
325             this.addComponent(name, componentType, rendererType);
326         }
327 
328         public void putComponent(String name, String componentType, String rendererType, 
329                                  Class<? extends TagHandler> handlerClass)
330         {
331             ParameterCheck.notNull("name", name);
332             ParameterCheck.notNull("componentType", componentType);
333             ParameterCheck.notNull("handlerClass", handlerClass);
334             this.addComponent(name, componentType, rendererType, handlerClass);
335         }
336 
337         public void putUserTag(String name, URL source)
338         {
339             ParameterCheck.notNull("name", name);
340             ParameterCheck.notNull("source", source);
341             this.addUserTag(name, source);
342         }
343 
344         public void putFunction(String name, Method method)
345         {
346             ParameterCheck.notNull("name", name);
347             ParameterCheck.notNull("method", method);
348             this.addFunction(name, method);
349         }
350         
351         public void putBehavior(String name, String id)
352         {
353             ParameterCheck.notNull("name", name);
354             ParameterCheck.notNull("id", id);
355             this.addBehavior(name, id);
356         }
357         
358         public void putBehavior(String name, String id, Class<? extends TagHandler> handlerClass)
359         {
360             ParameterCheck.notNull("name", name);
361             ParameterCheck.notNull("id", id);
362             ParameterCheck.notNull("handlerClass", handlerClass);
363             this.addBehavior(name, id, handlerClass);
364         }
365     }
366     
367     private static class ComponentConfigWrapper implements ComponentConfig
368     {
369 
370         protected final TagConfig parent;
371 
372         protected final String componentType;
373 
374         protected final String rendererType;
375 
376         public ComponentConfigWrapper(TagConfig parent, String componentType,
377                 String rendererType)
378         {
379             this.parent = parent;
380             this.componentType = componentType;
381             this.rendererType = rendererType;
382         }
383 
384         public String getComponentType()
385         {
386             return this.componentType;
387         }
388 
389         public String getRendererType()
390         {
391             return this.rendererType;
392         }
393 
394         public FaceletHandler getNextHandler()
395         {
396             return this.parent.getNextHandler();
397         }
398 
399         public Tag getTag()
400         {
401             return this.parent.getTag();
402         }
403 
404         public String getTagId()
405         {
406             return this.parent.getTagId();
407         }
408     }    
409     
410     private static class LibraryHandler extends DefaultHandler
411     {
412         private final URL source;
413         
414         private final FacesContext facesContext;
415 
416         private TagLibrary library;
417 
418         private final StringBuffer buffer;
419 
420         private Locator locator;
421 
422         private String tagName;
423 
424         private String converterId;
425 
426         private String validatorId;
427         
428         private String behaviorId;
429 
430         private String componentType;
431 
432         private String rendererType;
433 
434         private String functionName;
435 
436         private Class<? extends TagHandler> handlerClass;
437 
438         private Class<?> functionClass;
439 
440         private String functionSignature;
441         
442         private String compositeLibraryName;
443         
444         public LibraryHandler(FacesContext facesContext, URL source)
445         {
446             this.source = source;
447             this.buffer = new StringBuffer(64);
448             this.facesContext = facesContext;
449         }
450 
451         public TagLibrary getLibrary()
452         {
453             return this.library;
454         }
455 
456         public void endElement(String uri, String localName, String qName) throws SAXException
457         {
458             try
459             {
460                 if ("facelet-taglib".equals(qName))
461                 {
462                     // Nothing to do
463                 }                
464                 else if ("library-class".equals(qName))
465                 {
466                     this.processLibraryClass();
467                 }
468                 else if ("namespace".equals(qName))
469                 {
470                     this.library = new TagLibraryImpl(facesContext, this.captureBuffer());
471                     if (this.compositeLibraryName != null)
472                     {
473                         ((TagLibraryImpl)this.library).setCompositeLibrary(compositeLibraryName);
474                     }
475                 }
476                 else if ("composite-library-name".equals(qName))
477                 {
478                     this.compositeLibraryName = this.captureBuffer();
479                     if (this.library != null)
480                     {
481                         ((TagLibraryImpl)this.library).setCompositeLibrary(compositeLibraryName);
482                     }
483                 }
484                 else if ("component-type".equals(qName))
485                 {
486                     this.componentType = this.captureBuffer();
487                 }
488                 else if ("renderer-type".equals(qName))
489                 {
490                     this.rendererType = this.captureBufferEmptyNull();
491                 }
492                 else if ("tag-name".equals(qName))
493                 {
494                     this.tagName = this.captureBuffer();
495                 }
496                 else if ("function-name".equals(qName))
497                 {
498                     this.functionName = this.captureBuffer();
499                 }
500                 else if ("function-class".equals(qName))
501                 {
502                     String className = this.captureBuffer();
503                     this.functionClass = createClass(Object.class, className);
504                 }
505                 else if ("description".equals(qName))
506                 {
507                     //Not used
508                 }
509                 else if ("display-name".equals(qName))
510                 {
511                     //Not used
512                 }
513                 else if ("icon".equals(qName))
514                 {
515                     //Not used
516                 }                
517                 else
518                 {
519                     // Make sure there we've seen a namespace element
520                     // before trying any of the following elements to avoid
521                     // obscure NPEs
522                     if (this.library == null)
523                     {
524                         throw new IllegalStateException("No <namespace> element");
525                     }
526 
527                     TagLibraryImpl impl = (TagLibraryImpl) this.library;
528 
529                     if ("tag".equals(qName))
530                     {
531                         if (this.handlerClass != null)
532                         {
533                             impl.putTagHandler(this.tagName, this.handlerClass);
534                         }
535                     }
536                     else if ("handler-class".equals(qName))
537                     {
538                         String cName = this.captureBufferEmptyNull();
539                         this.handlerClass = createClass(TagHandler.class, cName);
540                     }
541                     else if ("component".equals(qName))
542                     {
543                         if (this.handlerClass != null)
544                         {
545                             impl.putComponent(this.tagName, this.componentType, this.rendererType, this.handlerClass);
546                             this.handlerClass = null;
547                         }
548                         else
549                         {
550                             impl.putComponent(this.tagName, this.componentType, this.rendererType);
551                         }
552                     }
553                     else if ("converter-id".equals(qName))
554                     {
555                         this.converterId = this.captureBuffer();
556                     }
557                     else if ("converter".equals(qName))
558                     {
559                         if (this.handlerClass != null)
560                         {
561                             impl.putConverter(this.tagName, this.converterId, handlerClass);
562                             this.handlerClass = null;
563                         }
564                         else
565                         {
566                             impl.putConverter(this.tagName, this.converterId);
567                         }
568                         this.converterId = null;
569                     }
570                     else if ("validator-id".equals(qName))
571                     {
572                         this.validatorId = this.captureBuffer();
573                     }
574                     else if ("validator".equals(qName))
575                     {
576                         if (this.handlerClass != null)
577                         {
578                             impl.putValidator(this.tagName, this.validatorId, handlerClass);
579                             this.handlerClass = null;
580                         }
581                         else
582                         {
583                             impl.putValidator(this.tagName, this.validatorId);
584                         }
585                         this.validatorId = null;
586                     }
587                     else if ("behavior-id".equals(qName))
588                     {
589                         this.behaviorId = this.captureBuffer();
590                     }
591                     else if ("behavior".equals(qName))
592                     {
593                         if (this.handlerClass != null)
594                         {
595                             impl.putBehavior(this.tagName, this.behaviorId, handlerClass);
596                             this.handlerClass = null;
597                         }
598                         else
599                         {
600                             impl.putBehavior(this.tagName, this.behaviorId);
601                         }
602                         this.behaviorId = null;
603                     }
604                     else if ("source".equals(qName))
605                     {
606                         String path = this.captureBuffer();
607                         URL url = new URL(this.source, path);
608                         impl.putUserTag(this.tagName, url);
609                     }
610                     else if ("function-signature".equals(qName))
611                     {
612                         this.functionSignature = this.captureBuffer();
613                         Method m = createMethod(this.functionClass, this.functionSignature);
614                         impl.putFunction(this.functionName, m);
615                     }
616                 }
617             }
618             catch (Exception e)
619             {
620                 throw new SAXParseException("Error Handling [" + this.source + "@" + this.locator.getLineNumber()
621                         + "," + this.locator.getColumnNumber() + "] <" + qName + ">", locator, e);
622             }
623         }
624 
625         private String captureBuffer() throws Exception
626         {
627             String s = this.buffer.toString().trim();
628             if (s.length() == 0)
629             {
630                 throw new Exception("Value Cannot be Empty");
631             }
632             this.buffer.setLength(0);
633             return s;
634         }
635 
636         private String captureBufferEmptyNull() throws Exception
637         {
638             String s = this.buffer.toString().trim();
639             if (s.length() == 0)
640             {
641                 //if is "" just set null instead
642                 s = null;
643             }
644             this.buffer.setLength(0);
645             return s;
646         }  
647 
648         @SuppressWarnings("unchecked")
649         private static <T> Class<? extends T> createClass(Class<T> type, String name) throws Exception
650         {
651             Class<? extends T> factory = (Class<? extends T>)ReflectionUtil.forName(name);
652             if (!type.isAssignableFrom(factory))
653             {
654                 throw new Exception(name + " must be an instance of " + type.getName());
655             }
656             return factory;
657         }
658 
659         private static Method createMethod(Class<?> type, String s) throws Exception
660         {
661             int pos = s.indexOf(' ');
662             if (pos == -1)
663             {
664                 throw new Exception("Must Provide Return Type: " + s);
665             }
666             else
667             {
668                 int pos2 = s.indexOf('(', pos + 1);
669                 if (pos2 == -1)
670                 {
671                     throw new Exception("Must provide a method name, followed by '(': " + s);
672                 }
673                 else
674                 {
675                     String mn = s.substring(pos + 1, pos2).trim();
676                     pos = s.indexOf(')', pos2 + 1);
677                     if (pos == -1)
678                     {
679                         throw new Exception("Must close parentheses, ')' missing: " + s);
680                     }
681                     else
682                     {
683                         String[] ps = s.substring(pos2 + 1, pos).trim().split(",");
684                         Class<?>[] pc;
685                         if (ps.length == 1 && "".equals(ps[0]))
686                         {
687                             pc = new Class[0];
688                         }
689                         else
690                         {
691                             pc = new Class[ps.length];
692                             for (int i = 0; i < pc.length; i++)
693                             {
694                                 pc[i] = ReflectionUtil.forName(ps[i].trim());
695                             }
696                         }
697                         try
698                         {
699                             return type.getMethod(mn, pc);
700                         }
701                         catch (NoSuchMethodException e)
702                         {
703                             throw new Exception("No Function Found on type: " + type.getName() + " with signature: "
704                                     + s);
705                         }
706 
707                     }
708 
709                 }
710             }
711         }
712 
713         private void processLibraryClass() throws Exception
714         {
715             String name = this.captureBuffer();
716             Class<?> type = createClass(TagLibrary.class, name);
717             this.library = (TagLibrary) type.newInstance();
718         }
719 
720         public InputSource resolveEntity(String publicId, String systemId) throws SAXException
721         {
722             if ("-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN".equals(publicId))
723             {
724                 URL url = ClassUtils.getResource("org/apache/myfaces/resource/facelet-taglib_1_0.dtd");
725                 return new InputSource(url.toExternalForm());
726             }
727             return null;
728         }
729 
730         public void characters(char[] ch, int start, int length) throws SAXException
731         {
732             this.buffer.append(ch, start, length);
733         }
734 
735         public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
736         {
737             this.buffer.setLength(0);
738             if ("tag".equals(qName))
739             {
740                 this.handlerClass = null;
741                 this.componentType = null;
742                 this.rendererType = null;
743                 this.tagName = null;
744             }
745             else if ("function".equals(qName))
746             {
747                 this.functionName = null;
748                 this.functionClass = null;
749                 this.functionSignature = null;
750             }
751         }
752 
753         public void error(SAXParseException e) throws SAXException
754         {
755             throw new SAXException(
756                     "Error Handling [" + this.source + "@" + e.getLineNumber() + "," + e.getColumnNumber() + "]", e);
757         }
758 
759         public void setDocumentLocator(Locator locator)
760         {
761             this.locator = locator;
762         }
763 
764         public void fatalError(SAXParseException e) throws SAXException
765         {
766             throw e;
767         }
768 
769         public void warning(SAXParseException e) throws SAXException
770         {
771             throw e;
772         }
773     }
774 
775     public TagLibraryConfig()
776     {
777         super();
778     }
779 
780     public static TagLibrary create(FacesContext facesContext, URL url) throws IOException
781     {
782         InputStream is = null;
783         TagLibrary t = null;
784         URLConnection conn = null;
785         try
786         {
787             ExternalContext externalContext = facesContext.getExternalContext();
788             boolean schemaValidating = false;
789 
790             // validate XML
791             if (MyfacesConfig.getCurrentInstance(externalContext).isValidateXML())
792             {
793                 String version = ConfigFilesXmlValidationUtils.getFaceletTagLibVersion(url);
794                 schemaValidating = "2.0".equals(version);
795                 if (schemaValidating)
796                 {
797                     ConfigFilesXmlValidationUtils.validateFaceletTagLibFile(url, externalContext, version);
798                 }
799             }
800             
801             // parse file
802             LibraryHandler handler = new LibraryHandler(facesContext, url);
803             SAXParser parser = createSAXParser(handler, externalContext, schemaValidating);
804             conn = url.openConnection();
805             conn.setUseCaches(false);
806             is = conn.getInputStream();
807             parser.parse(is, handler);
808             t = handler.getLibrary();
809         }
810         catch (SAXException e)
811         {
812             IOException ioe = new IOException("Error parsing [" + url + "]: ");
813             ioe.initCause(e);
814             throw ioe;
815         }
816         catch (ParserConfigurationException e)
817         {
818             IOException ioe = new IOException("Error parsing [" + url + "]: ");
819             ioe.initCause(e);
820             throw ioe;
821         }
822         finally
823         {
824             if (is != null)
825             {
826                 is.close();
827             }
828         }
829         return t;
830     }
831 
832     public void loadImplicit(FacesContext facesContext, Compiler compiler) throws IOException
833     {
834         //URL[] urls = Classpath.search(cl, "META-INF/", SUFFIX);
835         //for (int i = 0; i < urls.length; i++)
836         ExternalContext externalContext = facesContext.getExternalContext();
837         FaceletConfigResourceProvider provider = FaceletConfigResourceProviderFactory.
838             getFacesConfigResourceProviderFactory(externalContext).
839                 createFaceletConfigResourceProvider(externalContext);
840         Collection<URL> urls = provider.getFaceletTagLibConfigurationResources(externalContext);
841         for (URL url : urls)
842         {
843             try
844             {
845                 //TagLibrary tl = create(urls[i]);
846                 TagLibrary tl = create(facesContext, url);
847                 if (tl != null)
848                 {
849                     compiler.addTagLibrary(tl);
850                 }
851                 if (log.isLoggable(Level.FINE))
852                 {
853                     //log.fine("Added Library from: " + urls[i]);
854                     log.fine("Added Library from: " + url);
855                 }
856             }
857             catch (Exception e)
858             {
859                 //log.log(Level.SEVERE, "Error Loading Library: " + urls[i], e);
860                 log.log(Level.SEVERE, "Error Loading Library: " + url, e);
861             }
862         }
863     }
864 
865     private static final SAXParser createSAXParser(LibraryHandler handler, ExternalContext externalContext,
866                                                    boolean schemaValidating)
867             throws SAXException, ParserConfigurationException
868     {
869         SAXParserFactory factory = SAXParserFactory.newInstance();
870 
871         if (MyfacesConfig.getCurrentInstance(externalContext).isValidateXML() && !schemaValidating)
872         {
873             // DTD validating
874             factory.setNamespaceAware(false);
875             factory.setFeature("http://xml.org/sax/features/validation", true);
876             factory.setValidating(true);
877         }
878         else
879         {
880             //Just parse it and do not validate, because it is not necessary.
881             factory.setNamespaceAware(true);
882             factory.setFeature("http://xml.org/sax/features/validation", false);
883             factory.setValidating(false);
884         }
885 
886         SAXParser parser = factory.newSAXParser();
887         XMLReader reader = parser.getXMLReader();
888         reader.setErrorHandler(handler);
889         reader.setEntityResolver(handler);
890         return parser;
891     }
892 
893 }