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.tag;
20  
21  import java.lang.reflect.Constructor;
22  import java.lang.reflect.InvocationTargetException;
23  import java.lang.reflect.Method;
24  import java.net.URL;
25  import java.util.HashMap;
26  import java.util.Map;
27  
28  import javax.el.ELException;
29  import javax.faces.FacesException;
30  import javax.faces.view.facelets.BehaviorConfig;
31  import javax.faces.view.facelets.BehaviorHandler;
32  import javax.faces.view.facelets.ComponentConfig;
33  import javax.faces.view.facelets.ComponentHandler;
34  import javax.faces.view.facelets.ConverterConfig;
35  import javax.faces.view.facelets.ConverterHandler;
36  import javax.faces.view.facelets.FaceletException;
37  import javax.faces.view.facelets.FaceletHandler;
38  import javax.faces.view.facelets.Tag;
39  import javax.faces.view.facelets.TagConfig;
40  import javax.faces.view.facelets.TagHandler;
41  import javax.faces.view.facelets.ValidatorConfig;
42  import javax.faces.view.facelets.ValidatorHandler;
43  
44  /**
45   * Base class for defining TagLibraries in Java
46   * 
47   * @author Jacob Hookom
48   * @version $Id: AbstractTagLibrary.java 1187700 2011-10-22 12:19:37Z bommel $
49   */
50  public abstract class AbstractTagLibrary implements TagLibrary
51  {
52      private final Map<String, TagHandlerFactory> _factories;
53  
54      private final Map<String, Method> _functions;
55  
56      private final String _namespace;
57  
58      public AbstractTagLibrary(String namespace)
59      {
60          _namespace = namespace;
61          _factories = new HashMap<String, TagHandlerFactory>();
62          _functions = new HashMap<String, Method>();
63      }
64  
65      /*
66       * (non-Javadoc)
67       * 
68       * @see org.apache.myfaces.view.facelets.tag.TagLibrary#containsNamespace(java.lang.String)
69       */
70      public boolean containsNamespace(String ns)
71      {
72          return _namespace.equals(ns);
73      }
74  
75      /*
76       * (non-Javadoc)
77       * 
78       * @see org.apache.myfaces.view.facelets.tag.TagLibrary#containsTagHandler(java.lang.String, java.lang.String)
79       */
80      public boolean containsTagHandler(String ns, String localName)
81      {
82          return containsNamespace(ns) && _factories.containsKey(localName);
83      }
84  
85      /*
86       * (non-Javadoc)
87       * 
88       * @see org.apache.myfaces.view.facelets.tag.TagLibrary#createTagHandler(java.lang.String, java.lang.String,
89       * org.apache.myfaces.view.facelets.tag.TagConfig)
90       */
91      public TagHandler createTagHandler(String ns, String localName, TagConfig tag) throws FacesException
92      {
93          if (containsNamespace(ns))
94          {
95              TagHandlerFactory f = _factories.get(localName);
96              if (f != null)
97              {
98                  return f.createHandler(tag);
99              }
100         }
101         
102         return null;
103     }
104 
105     /*
106      * (non-Javadoc)
107      * 
108      * @see org.apache.myfaces.view.facelets.tag.TagLibrary#containsFunction(java.lang.String, java.lang.String)
109      */
110     public boolean containsFunction(String ns, String name)
111     {
112         return containsNamespace(ns) && _functions.containsKey(name);
113     }
114 
115     /*
116      * (non-Javadoc)
117      * 
118      * @see org.apache.myfaces.view.facelets.tag.TagLibrary#createFunction(java.lang.String, java.lang.String)
119      */
120     public Method createFunction(String ns, String name)
121     {
122         return containsNamespace(ns) ? _functions.get(name) : null;
123     }
124 
125     public String getNamespace()
126     {
127         return _namespace;
128     }
129 
130     /**
131      * Add a ComponentHandler with the specified componentType and rendererType, aliased by the tag name.
132      * 
133      * @see ComponentHandler
134      * @see javax.faces.application.Application#createComponent(java.lang.String)
135      * @param name
136      *            name to use, "foo" would be &lt;my:foo />
137      * @param componentType
138      *            componentType to use
139      * @param rendererType
140      *            rendererType to use
141      */
142     protected final void addComponent(String name, String componentType, String rendererType)
143     {
144         _factories.put(name, new ComponentHandlerFactory(componentType, rendererType));
145     }
146 
147     /**
148      * Add a ComponentHandler with the specified componentType and rendererType, aliased by the tag name. The Facelet
149      * will be compiled with the specified HandlerType (which must extend AbstractComponentHandler).
150      * 
151      * @see AbstractComponentHandler
152      * @param name
153      *            name to use, "foo" would be &lt;my:foo />
154      * @param componentType
155      *            componentType to use
156      * @param rendererType
157      *            rendererType to use
158      * @param handlerType
159      *            a Class that extends AbstractComponentHandler
160      */
161     protected final void addComponent(String name, String componentType, String rendererType, 
162                                       Class<? extends TagHandler> handlerType)
163     {
164         _factories.put(name, new UserComponentHandlerFactory(componentType, rendererType, handlerType));
165     }
166 
167     /**
168      * Add a ConvertHandler for the specified converterId
169      * 
170      * @see javax.faces.view.facelets.ConverterHandler
171      * @see javax.faces.application.Application#createConverter(java.lang.String)
172      * @param name
173      *            name to use, "foo" would be &lt;my:foo />
174      * @param converterId
175      *            id to pass to Application instance
176      */
177     protected final void addConverter(String name, String converterId)
178     {
179         _factories.put(name, new ConverterHandlerFactory(converterId));
180     }
181 
182     /**
183      * Add a ConvertHandler for the specified converterId of a TagHandler type
184      * 
185      * @see javax.faces.view.facelets.ConverterHandler
186      * @see javax.faces.view.facelets.ConverterConfig
187      * @see javax.faces.application.Application#createConverter(java.lang.String)
188      * @param name
189      *            name to use, "foo" would be &lt;my:foo />
190      * @param converterId
191      *            id to pass to Application instance
192      * @param type
193      *            TagHandler type that takes in a ConverterConfig
194      */
195     protected final void addConverter(String name, String converterId, Class<? extends TagHandler> type)
196     {
197         _factories.put(name, new UserConverterHandlerFactory(converterId, type));
198     }
199 
200     /**
201      * Add a ValidateHandler for the specified validatorId
202      * 
203      * @see javax.faces.view.facelets.ValidatorHandler
204      * @see javax.faces.application.Application#createValidator(java.lang.String)
205      * @param name
206      *            name to use, "foo" would be &lt;my:foo />
207      * @param validatorId
208      *            id to pass to Application instance
209      */
210     protected final void addValidator(String name, String validatorId)
211     {
212         _factories.put(name, new ValidatorHandlerFactory(validatorId));
213     }
214 
215     /**
216      * Add a ValidateHandler for the specified validatorId
217      * 
218      * @see javax.faces.view.facelets.ValidatorHandler
219      * @see javax.faces.view.facelets.ValidatorConfig
220      * @see javax.faces.application.Application#createValidator(java.lang.String)
221      * @param name
222      *            name to use, "foo" would be &lt;my:foo />
223      * @param validatorId
224      *            id to pass to Application instance
225      * @param type
226      *            TagHandler type that takes in a ValidatorConfig
227      */
228     protected final void addValidator(String name, String validatorId, Class<? extends TagHandler> type)
229     {
230         _factories.put(name, new UserValidatorHandlerFactory(validatorId, type));
231     }
232 
233     /**
234      * Use the specified HandlerType in compiling Facelets. HandlerType must extend TagHandler.
235      * 
236      * @see TagHandler
237      * @param name
238      *            name to use, "foo" would be &lt;my:foo />
239      * @param handlerType
240      *            must extend TagHandler
241      */
242     protected final void addTagHandler(String name, Class<? extends TagHandler> handlerType)
243     {
244         _factories.put(name, new HandlerFactory(handlerType));
245     }
246 
247     /**
248      * Add a UserTagHandler specified a the URL source.
249      * 
250      * @see UserTagHandler
251      * @param name
252      *            name to use, "foo" would be &lt;my:foo />
253      * @param source
254      *            source where the Facelet (Tag) source is
255      */
256     protected final void addUserTag(String name, URL source)
257     {
258         _factories.put(name, new UserTagFactory(source));
259     }
260 
261     /**
262      * Add a Method to be used as a Function at Compilation.
263      * 
264      * @see javax.el.FunctionMapper
265      * 
266      * @param name
267      *            (suffix) of function name
268      * @param method
269      *            method instance
270      */
271     protected final void addFunction(String name, Method method)
272     {
273         _functions.put(name, method);
274     }
275     
276     /**
277      * @since 2.0
278      * @param behaviorId
279      * @param behaviorClass
280      */
281     protected final void addBehavior(String name, String behaviorId)
282     {
283         _factories.put(name, new BehaviorHandlerFactory(behaviorId));
284     }
285     
286     /**
287      * @since 2.0
288      * @param behaviorId
289      * @param behaviorClass
290      * @param handlerType
291      */
292     protected final void addBehavior(String name, String behaviorId,
293             Class<? extends TagHandler> handlerType)
294     {
295         _factories.put(name, new UserBehaviorHandlerFactory(behaviorId,handlerType));
296     }    
297 
298     private static class ValidatorConfigWrapper implements ValidatorConfig
299     {
300 
301         private final TagConfig parent;
302         private final String validatorId;
303 
304         public ValidatorConfigWrapper(TagConfig parent, String validatorId)
305         {
306             this.parent = parent;
307             this.validatorId = validatorId;
308         }
309 
310         public String getValidatorId()
311         {
312             return this.validatorId;
313         }
314 
315         public FaceletHandler getNextHandler()
316         {
317             return this.parent.getNextHandler();
318         }
319 
320         public Tag getTag()
321         {
322             return this.parent.getTag();
323         }
324 
325         public String getTagId()
326         {
327             return this.parent.getTagId();
328         }
329     }
330 
331     private static class ConverterConfigWrapper implements ConverterConfig
332     {
333         private final TagConfig parent;
334         private final String converterId;
335 
336         public ConverterConfigWrapper(TagConfig parent, String converterId)
337         {
338             this.parent = parent;
339             this.converterId = converterId;
340         }
341 
342         public String getConverterId()
343         {
344             return this.converterId;
345         }
346 
347         public FaceletHandler getNextHandler()
348         {
349             return this.parent.getNextHandler();
350         }
351 
352         public Tag getTag()
353         {
354             return this.parent.getTag();
355         }
356 
357         public String getTagId()
358         {
359             return this.parent.getTagId();
360         }
361     }
362 
363     private static class HandlerFactory implements TagHandlerFactory
364     {
365         private final static Class<?>[] CONSTRUCTOR_SIG = new Class[]{TagConfig.class};
366 
367         protected final Class<? extends TagHandler> handlerType;
368 
369         public HandlerFactory(Class<? extends TagHandler> handlerType)
370         {
371             this.handlerType = handlerType;
372         }
373 
374         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
375         {
376             try
377             {
378                 return handlerType.getConstructor(CONSTRUCTOR_SIG).newInstance(new Object[] { cfg });
379             }
380             catch (InvocationTargetException ite)
381             {
382                 Throwable t = ite.getCause();
383                 if (t instanceof FacesException)
384                 {
385                     throw (FacesException) t;
386                 }
387                 else if (t instanceof ELException)
388                 {
389                     throw (ELException) t;
390                 }
391                 else
392                 {
393                     throw new FacesException("Error Instantiating: " + handlerType.getName(), t);
394                 }
395             }
396             catch (Exception e)
397             {
398                 throw new FacesException("Error Instantiating: " + handlerType.getName(), e);
399             }
400         }
401     }
402 
403     private static class ComponentConfigWrapper implements ComponentConfig
404     {
405 
406         protected final TagConfig parent;
407 
408         protected final String componentType;
409 
410         protected final String rendererType;
411 
412         public ComponentConfigWrapper(TagConfig parent, String componentType, String rendererType)
413         {
414             this.parent = parent;
415             this.componentType = componentType;
416             this.rendererType = rendererType;
417         }
418 
419         public String getComponentType()
420         {
421             return this.componentType;
422         }
423 
424         public String getRendererType()
425         {
426             return this.rendererType;
427         }
428 
429         public FaceletHandler getNextHandler()
430         {
431             return this.parent.getNextHandler();
432         }
433 
434         public Tag getTag()
435         {
436             return this.parent.getTag();
437         }
438 
439         public String getTagId()
440         {
441             return this.parent.getTagId();
442         }
443     }
444 
445     private static class UserTagFactory implements TagHandlerFactory
446     {
447         protected final URL location;
448 
449         public UserTagFactory(URL location)
450         {
451             this.location = location;
452         }
453 
454         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
455         {
456             return new UserTagHandler(cfg, this.location);
457         }
458     }
459 
460     private static class ComponentHandlerFactory implements TagHandlerFactory
461     {
462 
463         protected final String componentType;
464 
465         protected final String renderType;
466 
467         /**
468          * @param handlerType
469          */
470         public ComponentHandlerFactory(String componentType, String renderType)
471         {
472             this.componentType = componentType;
473             this.renderType = renderType;
474         }
475 
476         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
477         {
478             ComponentConfig ccfg = new ComponentConfigWrapper(cfg, this.componentType, this.renderType);
479             return new ComponentHandler(ccfg);
480         }
481     }
482 
483     private static class UserComponentHandlerFactory implements TagHandlerFactory
484     {
485 
486         private final static Class<?>[] CONS_SIG = new Class[] { ComponentConfig.class };
487 
488         protected final String componentType;
489 
490         protected final String renderType;
491 
492         protected final Class<? extends TagHandler> type;
493 
494         protected final Constructor<? extends TagHandler> constructor;
495 
496         /**
497          * @param handlerType
498          */
499         public UserComponentHandlerFactory(String componentType, String renderType, Class<? extends TagHandler> type)
500         {
501             this.componentType = componentType;
502             this.renderType = renderType;
503             this.type = type;
504             try
505             {
506                 this.constructor = this.type.getConstructor(CONS_SIG);
507             }
508             catch (Exception e)
509             {
510                 throw new FaceletException("Must have a Constructor that takes in a ComponentConfig", e);
511             }
512         }
513 
514         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
515         {
516             try
517             {
518                 ComponentConfig ccfg = new ComponentConfigWrapper(cfg, componentType, renderType);
519                 return constructor.newInstance(new Object[] { ccfg });
520             }
521             catch (InvocationTargetException e)
522             {
523                 throw new FaceletException(e.getCause().getMessage(), e.getCause().getCause());
524             }
525             catch (Exception e)
526             {
527                 throw new FaceletException("Error Instantiating ComponentHandler: " + this.type.getName(), e);
528             }
529         }
530     }
531 
532     private static class ValidatorHandlerFactory implements TagHandlerFactory
533     {
534 
535         protected final String validatorId;
536 
537         public ValidatorHandlerFactory(String validatorId)
538         {
539             this.validatorId = validatorId;
540         }
541 
542         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
543         {
544             return new ValidatorHandler(new ValidatorConfigWrapper(cfg, this.validatorId));
545         }
546     }
547 
548     private static class ConverterHandlerFactory implements TagHandlerFactory
549     {
550 
551         protected final String converterId;
552 
553         public ConverterHandlerFactory(String converterId)
554         {
555             this.converterId = converterId;
556         }
557 
558         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
559         {
560             return new ConverterHandler(new ConverterConfigWrapper(cfg, this.converterId));
561         }
562     }
563 
564     private static class UserConverterHandlerFactory implements TagHandlerFactory
565     {
566         private final static Class<?>[] CONS_SIG = new Class[] { ConverterConfig.class };
567 
568         protected final String converterId;
569 
570         protected final Class<? extends TagHandler> type;
571 
572         protected final Constructor<? extends TagHandler> constructor;
573 
574         public UserConverterHandlerFactory(String converterId, Class<? extends TagHandler> type)
575         {
576             this.converterId = converterId;
577             this.type = type;
578             try
579             {
580                 this.constructor = this.type.getConstructor(CONS_SIG);
581             }
582             catch (Exception e)
583             {
584                 throw new FaceletException("Must have a Constructor that takes in a ConverterConfig", e);
585             }
586         }
587 
588         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
589         {
590             try
591             {
592                 ConverterConfig ccfg = new ConverterConfigWrapper(cfg, converterId);
593                 return constructor.newInstance(new Object[] { ccfg });
594             }
595             catch (InvocationTargetException e)
596             {
597                 throw new FaceletException(e.getCause().getMessage(), e.getCause().getCause());
598             }
599             catch (Exception e)
600             {
601                 throw new FaceletException("Error Instantiating ConverterHandler: " + type.getName(), e);
602             }
603         }
604     }
605 
606     private static class UserValidatorHandlerFactory implements TagHandlerFactory
607     {
608         private final static Class<?>[] CONS_SIG = new Class[] { ValidatorConfig.class };
609 
610         protected final String validatorId;
611 
612         protected final Class<? extends TagHandler> type;
613 
614         protected final Constructor<? extends TagHandler> constructor;
615 
616         public UserValidatorHandlerFactory(String validatorId, Class<? extends TagHandler> type)
617         {
618             this.validatorId = validatorId;
619             this.type = type;
620             try
621             {
622                 this.constructor = this.type.getConstructor(CONS_SIG);
623             }
624             catch (Exception e)
625             {
626                 throw new FaceletException("Must have a Constructor that takes in a ConverterConfig", e);
627             }
628         }
629 
630         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
631         {
632             try
633             {
634                 ValidatorConfig ccfg = new ValidatorConfigWrapper(cfg, validatorId);
635                 return constructor.newInstance(new Object[] { ccfg });
636             }
637             catch (InvocationTargetException e)
638             {
639                 throw new FaceletException(e.getCause().getMessage(), e.getCause().getCause());
640             }
641             catch (Exception e)
642             {
643                 throw new FaceletException("Error Instantiating ValidatorHandler: " + type.getName(), e);
644             }
645         }
646     }
647     
648     private static class BehaviorConfigWrapper implements BehaviorConfig
649     {
650         protected final TagConfig parent;
651 
652         protected final String behaviorId;
653 
654         public BehaviorConfigWrapper(TagConfig parent, String behaviorId)
655         {
656             this.parent = parent;
657             this.behaviorId = behaviorId;
658         }
659 
660         public FaceletHandler getNextHandler()
661         {
662             return this.parent.getNextHandler();
663         }
664 
665         public Tag getTag()
666         {
667             return this.parent.getTag();
668         }
669 
670         public String getTagId()
671         {
672             return this.parent.getTagId();
673         }
674 
675         public String getBehaviorId()
676         {
677             return this.behaviorId;
678         }
679     }
680     
681     private static class BehaviorHandlerFactory implements TagHandlerFactory
682     {
683         protected final String behaviorId;
684                
685         public BehaviorHandlerFactory(String behaviorId)
686         {
687             super();
688             this.behaviorId = behaviorId;
689         }
690 
691         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
692         {
693             BehaviorConfig bcfg = new BehaviorConfigWrapper(cfg,this.behaviorId);
694             return new BehaviorHandler(bcfg);
695         }
696     }
697 
698     private static class UserBehaviorHandlerFactory implements TagHandlerFactory
699     {
700         private final static Class<?>[] CONS_SIG = new Class[] { BehaviorConfig.class };
701 
702         protected final String behaviorId;
703 
704         protected final Class<? extends TagHandler> type;
705 
706         protected final Constructor<? extends TagHandler> constructor;
707 
708         public UserBehaviorHandlerFactory(String behaviorId, Class<? extends TagHandler> type)
709         {
710             this.behaviorId = behaviorId;
711             this.type = type;
712             try
713             {
714                 this.constructor = this.type.getConstructor(CONS_SIG);
715             }
716             catch (Exception e)
717             {
718                 throw new FaceletException("Must have a Constructor that takes in a BehaviorConfig", e);
719             }
720         }
721 
722         public TagHandler createHandler(TagConfig cfg) throws FacesException, ELException
723         {
724             try
725             {
726                 BehaviorConfig bcfg = new BehaviorConfigWrapper(cfg,this.behaviorId);
727                 return constructor.newInstance(new Object[] { bcfg });
728             }
729             catch (InvocationTargetException e)
730             {
731                 throw new FaceletException(e.getCause().getMessage(), e.getCause().getCause());
732             }
733             catch (Exception e)
734             {
735                 throw new FaceletException("Error Instantiating BehaviorHandler: " + this.type.getName(), e);
736             }
737         }
738     }
739 }