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.application;
20  
21  import java.lang.reflect.Constructor;
22  import java.util.ArrayList;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Locale;
28  import java.util.Map;
29  import java.util.MissingResourceException;
30  import java.util.concurrent.ConcurrentHashMap;
31  
32  import javax.el.CompositeELResolver;
33  import javax.el.ELContext;
34  import javax.el.ELContextListener;
35  import javax.el.ELException;
36  import javax.el.ELResolver;
37  import javax.el.ExpressionFactory;
38  import javax.el.MethodExpression;
39  import javax.el.ValueExpression;
40  import javax.faces.FacesException;
41  import javax.faces.application.Application;
42  import javax.faces.application.NavigationHandler;
43  import javax.faces.application.StateManager;
44  import javax.faces.application.ViewHandler;
45  import javax.faces.component.UIComponent;
46  import javax.faces.component.UIViewRoot;
47  import javax.faces.context.FacesContext;
48  import javax.faces.convert.Converter;
49  import javax.faces.el.MethodBinding;
50  import javax.faces.el.PropertyResolver;
51  import javax.faces.el.ReferenceSyntaxException;
52  import javax.faces.el.ValueBinding;
53  import javax.faces.el.VariableResolver;
54  import javax.faces.event.ActionListener;
55  import javax.faces.validator.Validator;
56  
57  import org.apache.commons.beanutils.BeanUtils;
58  import org.apache.commons.logging.Log;
59  import org.apache.commons.logging.LogFactory;
60  import org.apache.myfaces.application.jsp.JspStateManagerImpl;
61  import org.apache.myfaces.application.jsp.JspViewHandlerImpl;
62  import org.apache.myfaces.config.RuntimeConfig;
63  import org.apache.myfaces.config.impl.digester.elements.Property;
64  import org.apache.myfaces.config.impl.digester.elements.ResourceBundle;
65  import org.apache.myfaces.el.PropertyResolverImpl;
66  import org.apache.myfaces.el.VariableResolverToApplicationELResolverAdapter;
67  import org.apache.myfaces.el.convert.MethodExpressionToMethodBinding;
68  import org.apache.myfaces.el.convert.ValueBindingToValueExpression;
69  import org.apache.myfaces.el.convert.ValueExpressionToValueBinding;
70  import org.apache.myfaces.el.unified.ELResolverBuilder;
71  import org.apache.myfaces.el.unified.ResolverBuilderForFaces;
72  import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver;
73  import org.apache.myfaces.el.unified.resolver.FacesCompositeELResolver.Scope;
74  import org.apache.myfaces.shared_impl.util.ClassUtils;
75  
76  /**
77   * DOCUMENT ME!
78   *
79   * @author Manfred Geiler (latest modification by $Author: lu4242 $)
80   * @author Anton Koinov
81   * @author Thomas Spiegl
82   * @author Stan Silvert
83   * @version $Revision: 1136229 $ $Date: 2011-06-15 17:38:34 -0500 (Wed, 15 Jun 2011) $
84   */
85  @SuppressWarnings("deprecation")
86  public class ApplicationImpl extends Application
87  {
88      private static final Log log = LogFactory.getLog(ApplicationImpl.class);
89  
90      private final static VariableResolver VARIABLERESOLVER = new VariableResolverToApplicationELResolverAdapter();
91  
92      private final static PropertyResolver PROPERTYRESOLVER = new PropertyResolverImpl();
93  
94      // ~ Instance fields
95      // ----------------------------------------------------------------------------
96  
97      private Collection<Locale> _supportedLocales = Collections.emptySet();
98      private Locale _defaultLocale;
99      private String _messageBundle;
100 
101     private ViewHandler _viewHandler;
102     private NavigationHandler _navigationHandler;
103     private ActionListener _actionListener;
104     private String _defaultRenderKitId;
105     private StateManager _stateManager;
106 
107     private ArrayList<ELContextListener> _elContextListeners;
108 
109     // components, converters, and validators can be added at runtime--must
110     // synchronize, uses ConcurrentHashMap to allow concurrent read of map
111     private final Map<String, Class> _converterIdToClassMap = new ConcurrentHashMap<String, Class>();
112     private final Map<Class, String> _converterClassNameToClassMap = new ConcurrentHashMap<Class, String>();
113     private final Map<String, Class> _componentClassMap = new ConcurrentHashMap<String, Class>();
114     private final Map<String, Class> _validatorClassMap = new ConcurrentHashMap<String, Class>();
115 
116     private final RuntimeConfig _runtimeConfig;
117 
118     private ELResolver elResolver;
119 
120     private ELResolverBuilder resolverBuilderForFaces;
121 
122     private List<Class<? extends Converter>> _noArgConstructorConverterClasses
123             = new ArrayList<Class<? extends Converter>>();
124 
125     // ~ Constructors
126     // -------------------------------------------------------------------------------
127 
128     public ApplicationImpl()
129     {
130         this(getRuntimeConfig());
131     }
132 
133     private static RuntimeConfig getRuntimeConfig()
134     {
135         return RuntimeConfig.getCurrentInstance(
136                 FacesContext.getCurrentInstance().getExternalContext());
137     }
138 
139     ApplicationImpl(final RuntimeConfig runtimeConfig)
140     {
141         if (runtimeConfig == null)
142         {
143             throw new IllegalArgumentException("runtimeConfig must mot be null");
144         }
145         // set default implementation in constructor
146         // pragmatic approach, no syncronizing will be needed in get methods
147         _viewHandler = new JspViewHandlerImpl();
148         _navigationHandler = new NavigationHandlerImpl();
149         _actionListener = new ActionListenerImpl();
150         _defaultRenderKitId = "HTML_BASIC";
151         _stateManager = new JspStateManagerImpl();
152         _elContextListeners = new ArrayList<ELContextListener>();
153         _runtimeConfig = runtimeConfig;
154 
155         if (log.isTraceEnabled())
156             log.trace("New Application instance created");
157     }
158 
159     // ~ Methods
160     // ------------------------------------------------------------------------------------
161 
162     @Override
163     public final void addELResolver(final ELResolver resolver)
164     {
165         if (FacesContext.getCurrentInstance() != null)
166         {
167             throw new IllegalStateException("It is illegal to add a resolver after the first request is processed");
168         }
169         if (resolver != null)
170         {
171             _runtimeConfig.addApplicationElResolver(resolver);
172         }
173     }
174 
175     @Override
176     public final ELResolver getELResolver()
177     {
178         // we don't need synchronization here since it is ok to have multiple
179         // instances of the elresolver
180         if (elResolver == null)
181         {
182             elResolver = createFacesResolver();
183         }
184         return elResolver;
185     }
186 
187     private ELResolver createFacesResolver()
188     {
189         final CompositeELResolver resolver = new FacesCompositeELResolver(Scope.Faces);
190         getResolverBuilderForFaces().build(resolver);
191         return resolver;
192     }
193 
194     protected final ELResolverBuilder getResolverBuilderForFaces()
195     {
196         if (resolverBuilderForFaces == null)
197         {
198             resolverBuilderForFaces = new ResolverBuilderForFaces(_runtimeConfig);
199         }
200         return resolverBuilderForFaces;
201     }
202 
203     public final void setResolverBuilderForFaces(final ELResolverBuilder factory)
204     {
205         resolverBuilderForFaces = factory;
206     }
207 
208     @Override
209     public final java.util.ResourceBundle getResourceBundle(final FacesContext facesContext, final String name) throws FacesException,
210             NullPointerException
211     {
212 
213         checkNull(facesContext, "facesContext");
214         checkNull(name, "name");
215 
216         final String bundleName = getBundleName(facesContext, name);
217 
218         if (bundleName == null)
219         {
220             return null;
221         }
222 
223         Locale locale = Locale.getDefault();
224 
225         final UIViewRoot viewRoot = facesContext.getViewRoot();
226         if (viewRoot != null && viewRoot.getLocale() != null)
227         {
228             locale = viewRoot.getLocale();
229         }
230 
231         try
232         {
233             return getResourceBundle(bundleName, locale, getClassLoader());
234         }
235         catch (MissingResourceException e)
236         {
237             try
238             {
239                 return getResourceBundle(bundleName, locale, this.getClass().getClassLoader());
240             }
241             catch (MissingResourceException e1)
242             {            
243                 throw new FacesException("Could not load resource bundle for name '" + name + "': " + e.getMessage(), e1);
244             }
245         }
246     }
247 
248     private ClassLoader getClassLoader()
249     {
250         return ClassUtils.getContextClassLoader();
251     }
252 
253     String getBundleName(final FacesContext facesContext, final String name)
254     {
255         ResourceBundle bundle = getRuntimeConfig(facesContext).getResourceBundle(name);
256         return bundle != null ? bundle.getBaseName() : null;
257     }
258 
259     java.util.ResourceBundle getResourceBundle(final String name, final Locale locale, final ClassLoader loader)
260             throws MissingResourceException
261     {
262         return java.util.ResourceBundle.getBundle(name, locale, loader);
263     }
264 
265     final RuntimeConfig getRuntimeConfig(final FacesContext facesContext)
266     {
267         return RuntimeConfig.getCurrentInstance(facesContext.getExternalContext());
268     }
269 
270     final FacesContext getFaceContext()
271     {
272         return FacesContext.getCurrentInstance();
273     }
274 
275     @Override
276     public final UIComponent createComponent(final ValueExpression componentExpression, final FacesContext facesContext,
277             final String componentType) throws FacesException, NullPointerException
278     {
279 
280         checkNull(componentExpression, "componentExpression");
281         checkNull(facesContext, "facesContext");
282         checkNull(componentType, "componentType");
283 
284         final ELContext elContext = facesContext.getELContext();
285 
286         try
287         {
288             final Object retVal = componentExpression.getValue(elContext);
289 
290             UIComponent createdComponent;
291 
292             if (retVal instanceof UIComponent)
293             {
294                 createdComponent = (UIComponent) retVal;
295             }
296             else
297             {
298                 createdComponent = createComponent(componentType);
299                 componentExpression.setValue(elContext, createdComponent);
300             }
301 
302             return createdComponent;
303         }
304         catch (FacesException e)
305         {
306             throw e;
307         }
308         catch (Exception e)
309         {
310             throw new FacesException(e);
311         }
312     }
313 
314     @Override
315     public final ExpressionFactory getExpressionFactory()
316     {
317         return _runtimeConfig.getExpressionFactory();
318     }
319 
320     @Override
321     public final Object evaluateExpressionGet(final FacesContext context, final String expression, final Class expectedType) throws ELException
322     {
323         ELContext elContext = context.getELContext();
324         return getExpressionFactory().createValueExpression(elContext, expression, expectedType).getValue(elContext);
325     }
326 
327     @Override
328     public final void addELContextListener(final ELContextListener listener)
329     {
330 
331         synchronized (_elContextListeners)
332         {
333             _elContextListeners.add(listener);
334         }
335     }
336 
337     @Override
338     public final void removeELContextListener(final ELContextListener listener)
339     {
340         synchronized (_elContextListeners)
341         {
342             _elContextListeners.remove(listener);
343         }
344     }
345 
346     @Override
347     public final ELContextListener[] getELContextListeners()
348     {
349         // this gets called on every request, so I can't afford to synchronize
350         // I just have to trust that toArray() with do the right thing if the
351         // list is changing (not likely)
352         return _elContextListeners.toArray(new ELContextListener[_elContextListeners.size()]);
353     }
354 
355     @Override
356     public final void setActionListener(final ActionListener actionListener)
357     {
358         checkNull(actionListener, "actionListener");
359 
360         _actionListener = actionListener;
361         if (log.isTraceEnabled())
362             log.trace("set actionListener = " + actionListener.getClass().getName());
363     }
364 
365     @Override
366     public final ActionListener getActionListener()
367     {
368         return _actionListener;
369     }
370 
371     @Override
372     public final Iterator<String> getComponentTypes()
373     {
374         return _componentClassMap.keySet().iterator();
375     }
376 
377     @Override
378     public final Iterator<String> getConverterIds()
379     {
380         return _converterIdToClassMap.keySet().iterator();
381     }
382 
383     @Override
384     public final Iterator<Class> getConverterTypes()
385     {
386         return _converterClassNameToClassMap.keySet().iterator();
387     }
388 
389     @Override
390     public final void setDefaultLocale(final Locale locale)
391     {
392         checkNull(locale, "locale");
393 
394         _defaultLocale = locale;
395         if (log.isTraceEnabled())
396             log.trace("set defaultLocale = " + locale.getCountry() + " " + locale.getLanguage());
397     }
398 
399     @Override
400     public final Locale getDefaultLocale()
401     {
402         return _defaultLocale;
403     }
404 
405     @Override
406     public final void setMessageBundle(final String messageBundle)
407     {
408         checkNull(messageBundle, "messageBundle");
409 
410         _messageBundle = messageBundle;
411         if (log.isTraceEnabled())
412             log.trace("set MessageBundle = " + messageBundle);
413     }
414 
415     @Override
416     public final String getMessageBundle()
417     {
418         return _messageBundle;
419     }
420 
421     @Override
422     public final void setNavigationHandler(final NavigationHandler navigationHandler)
423     {
424         checkNull(navigationHandler, "navigationHandler");
425 
426         _navigationHandler = navigationHandler;
427         if (log.isTraceEnabled())
428             log.trace("set NavigationHandler = " + navigationHandler.getClass().getName());
429     }
430 
431     @Override
432     public final NavigationHandler getNavigationHandler()
433     {
434         return _navigationHandler;
435     }
436 
437     /**
438      * @deprecated
439      */
440     @Deprecated
441     @Override
442     public final void setPropertyResolver(final PropertyResolver propertyResolver)
443     {
444         checkNull(propertyResolver, "propertyResolver");
445 
446         if (getFaceContext() != null)
447         {
448             throw new IllegalStateException("propertyResolver must be defined before request processing");
449         }
450 
451         _runtimeConfig.setPropertyResolver(propertyResolver);
452 
453         if (log.isTraceEnabled())
454             log.trace("set PropertyResolver = " + propertyResolver.getClass().getName());
455     }
456 
457     /**
458      * @deprecated
459      */
460     @Deprecated
461     @Override
462     public final PropertyResolver getPropertyResolver()
463     {
464         return PROPERTYRESOLVER;
465     }
466 
467     @Override
468     public final void setSupportedLocales(final Collection<Locale> locales)
469     {
470         checkNull(locales, "locales");
471 
472         _supportedLocales = locales;
473         if (log.isTraceEnabled())
474             log.trace("set SupportedLocales");
475     }
476 
477     @Override
478     public final Iterator<Locale> getSupportedLocales()
479     {
480         return _supportedLocales.iterator();
481     }
482 
483     @Override
484     public final Iterator<String> getValidatorIds()
485     {
486         return _validatorClassMap.keySet().iterator();
487     }
488 
489     /**
490      * @deprecated
491      */
492     @Deprecated
493     @Override
494     public final void setVariableResolver(final VariableResolver variableResolver)
495     {
496         checkNull(variableResolver, "variableResolver");
497 
498         if (getFaceContext() != null)
499         {
500             throw new IllegalStateException("variableResolver must be defined before request processing");
501         }
502 
503         _runtimeConfig.setVariableResolver(variableResolver);
504 
505         if (log.isTraceEnabled())
506             log.trace("set VariableResolver = " + variableResolver.getClass().getName());
507     }
508 
509     /**
510      * @deprecated
511      */
512     @Deprecated
513     @Override
514     public final VariableResolver getVariableResolver()
515     {
516         return VARIABLERESOLVER;
517     }
518 
519     @Override
520     public final void setViewHandler(final ViewHandler viewHandler)
521     {
522         checkNull(viewHandler, "viewHandler");
523 
524         _viewHandler = viewHandler;
525         if (log.isTraceEnabled())
526             log.trace("set ViewHandler = " + viewHandler.getClass().getName());
527     }
528 
529     @Override
530     public final ViewHandler getViewHandler()
531     {
532         return _viewHandler;
533     }
534 
535     @Override
536     public final void addComponent(final String componentType, final String componentClassName)
537     {
538         checkNull(componentType, "componentType");
539         checkEmpty(componentType, "componentType");
540         checkNull(componentClassName, "componentClassName");
541         checkEmpty(componentClassName, "componentClassName");
542 
543         try
544         {
545             _componentClassMap.put(componentType, ClassUtils.simpleClassForName(componentClassName));
546             if (log.isTraceEnabled())
547                 log.trace("add Component class = " + componentClassName + " for type = " + componentType);
548         }
549         catch (Exception e)
550         {
551             log.error("Component class " + componentClassName + " not found", e);
552         }
553     }
554 
555     @Override
556     public final void addConverter(final String converterId, final String converterClass)
557     {
558         checkNull(converterId, "converterId");
559         checkEmpty(converterId, "converterId");
560         checkNull(converterClass, "converterClass");
561         checkEmpty(converterClass, "converterClass");
562 
563         try
564         {
565             _converterIdToClassMap.put(converterId, ClassUtils.simpleClassForName(converterClass));
566             if (log.isTraceEnabled())
567                 log.trace("add Converter id = " + converterId + " converterClass = " + converterClass);
568         }
569         catch (Exception e)
570         {
571             log.error("Converter class " + converterClass + " not found", e);
572         }
573     }
574 
575     @Override
576     public final void addConverter(final Class targetClass, final String converterClass)
577     {
578         checkNull(targetClass, "targetClass");
579         checkNull(converterClass, "converterClass");
580         checkEmpty(converterClass, "converterClass");
581 
582         try
583         {
584             _converterClassNameToClassMap.put(targetClass, converterClass);
585             if (log.isTraceEnabled())
586                 log.trace("add Converter for class = " + targetClass + " converterClass = " + converterClass);
587         }
588         catch (Exception e)
589         {
590             log.error("Converter class " + converterClass + " not found", e);
591         }
592     }
593 
594     @Override
595     public final void addValidator(final String validatorId, final String validatorClass)
596     {
597         checkNull(validatorId, "validatorId");
598         checkEmpty(validatorId, "validatorId");
599         checkNull(validatorClass, "validatorClass");
600         checkEmpty(validatorClass, "validatorClass");
601 
602         try
603         {
604             _validatorClassMap.put(validatorId, ClassUtils.simpleClassForName(validatorClass));
605             if (log.isTraceEnabled())
606                 log.trace("add Validator id = " + validatorId + " class = " + validatorClass);
607         }
608         catch (Exception e)
609         {
610             log.error("Validator class " + validatorClass + " not found", e);
611         }
612     }
613 
614     @Override
615     public final UIComponent createComponent(final String componentType) throws FacesException
616     {
617         checkNull(componentType, "componentType");
618         checkEmpty(componentType, "componentType");
619 
620         final Class componentClass = _componentClassMap.get(componentType);
621         if (componentClass == null)
622         {
623             log.error("Undefined component type " + componentType);
624             throw new FacesException("Undefined component type " + componentType);
625         }
626 
627         try
628         {
629             return (UIComponent) componentClass.newInstance();
630         }
631         catch (Exception e)
632         {
633             log.error("Could not instantiate component componentType = " + componentType, e);
634             throw new FacesException("Could not instantiate component componentType = " + componentType, e);
635         }
636     }
637 
638     /**
639      * @deprecated Use createComponent(ValueExpression, FacesContext, String) instead.
640      */
641     @Deprecated
642     @Override
643     public final UIComponent createComponent(final ValueBinding valueBinding, final FacesContext facesContext,
644             final String componentType) throws FacesException
645     {
646 
647         checkNull(valueBinding, "valueBinding");
648         checkNull(facesContext, "facesContext");
649         checkNull(componentType, "componentType");
650         checkEmpty(componentType, "componentType");
651 
652         final ValueExpression valExpression = new ValueBindingToValueExpression(valueBinding);
653 
654         return createComponent(valExpression, facesContext, componentType);
655     }
656 
657     /**
658      * Return an instance of the converter class that has been registered under
659      * the specified id.
660      * <p>
661      * Converters are registered via faces-config.xml files, and can also be registered
662      * via the addConverter(String id, Class converterClass) method on this class. Here
663      * the the appropriate Class definition is found, then an instance is created and
664      * returned.
665      * <p>
666      * A converter registered via a config file can have any number of nested attribute or
667      * property tags. The JSF specification is very vague about what effect these nested
668      * tags have. This method ignores nested attribute definitions, but for each nested
669      * property tag the corresponding setter is invoked on the new Converter instance
670      * passing the property's defaultValuer. Basic typeconversion is done so the target
671      * properties on the Converter instance can be String, int, boolean, etc. Note that:
672      * <ol>
673      * <li>the Sun Mojarra JSF implemenation ignores nested property tags completely, so
674      * this behaviour cannot be relied on across implementations.
675      * <li>there is no equivalent functionality for converter classes registered via
676      * the Application.addConverter api method.
677      * </ol>
678      * <p>
679      * Note that this method is most commonly called from the standard f:attribute tag.
680      * As an alternative, most components provide a "converter" attribute which uses an
681      * EL expression to create a Converter instance, in which case this method is not
682      * invoked at all. The converter attribute allows the returned Converter instance to
683      * be configured via normal dependency-injection, and is generally a better choice
684      * than using this method.
685      */
686     @Override
687     public final Converter createConverter(final String converterId)
688     {
689         checkNull(converterId, "converterId");
690         checkEmpty(converterId, "converterId");
691 
692         final Class converterClass = _converterIdToClassMap.get(converterId);
693         if(converterClass == null)
694         {
695             throw new FacesException("Could not find any registered converter-class by converterId : "+converterId);
696         }
697 
698         try
699         {
700             final Converter converter = (Converter) converterClass.newInstance();
701 
702             setConverterProperties(converterClass, converter);
703 
704             return converter;
705         }
706         catch (Exception e)
707         {
708             log.error("Could not instantiate converter " + converterClass, e);
709             throw new FacesException("Could not instantiate converter: " + converterClass, e);
710         }
711     }
712 
713     @Override
714     public final Converter createConverter(final Class targetClass)
715     {
716         checkNull(targetClass, "targetClass");
717 
718         return internalCreateConverter(targetClass);
719     }
720 
721     private Converter internalCreateConverter(final Class targetClass)
722     {
723         // Locate a Converter registered for the target class itself.
724         String converterClassName = _converterClassNameToClassMap.get(targetClass);
725 
726         // Locate a Converter registered for interfaces that are
727         // implemented by the target class (directly or indirectly).
728         if (converterClassName == null)
729         {
730             final Class interfaces[] = targetClass.getInterfaces();
731             if (interfaces != null)
732             {
733                 for (int i = 0, len = interfaces.length; i < len; i++)
734                 {
735                     // search all superinterfaces for a matching converter,
736                     // create it
737                     final Converter converter = internalCreateConverter(interfaces[i]);
738                     if (converter != null)
739                     {
740                         return converter;
741                     }
742                 }
743             }
744         }
745 
746         // Get EnumConverter for enum classes with no special converter, check
747         // here as recursive call with java.lang.Enum will not work
748         if (converterClassName == null && targetClass.isEnum()) {
749             converterClassName = _converterClassNameToClassMap.get(Enum.class);
750         }
751 
752         if (converterClassName != null)
753         {
754             try
755             {
756                 Class<? extends Converter> converterClass = ClassUtils.simpleClassForName(converterClassName);
757                 Converter converter = null;
758 
759                 // check cached constructor information
760                 if (!_noArgConstructorConverterClasses.contains(converterClass))
761                 {
762                     // the converter class either supports the one-arg constructor
763                     // or has never been processed before
764                     try
765                     {
766                         // look for a constructor that takes a single Class object
767                         // See JSF 1.2 javadoc for Converter
768                         Constructor<? extends Converter> constructor = converterClass
769                                 .getConstructor(new Class[] { Class.class });
770 
771                         converter = constructor.newInstance(new Object[] { targetClass });
772                     }
773                     catch (Exception e)
774                     {
775                         // the constructor does not exist
776                         // add the class to the no-arg constructor classes cache
777                         _noArgConstructorConverterClasses.add(converterClass);
778 
779                         // use no-arg constructor
780                         converter = converterClass.newInstance();
781                     }
782                 }
783                 else
784                 {
785                     // use no-arg constructor
786                     converter = converterClass.newInstance();
787                 }
788 
789                 setConverterProperties(converterClass, converter);
790 
791                 return converter;
792             }
793             catch (Exception e)
794             {
795                 log.error("Could not instantiate converter " + converterClassName, e);
796                 throw new FacesException("Could not instantiate converter: " + converterClassName, e);
797             }
798         }
799 
800         // locate converter for primitive types
801         if (targetClass == Long.TYPE)
802         {
803             return internalCreateConverter(Long.class);
804         }
805         else if (targetClass == Boolean.TYPE)
806         {
807             return internalCreateConverter(Boolean.class);
808         }
809         else if (targetClass == Double.TYPE)
810         {
811             return internalCreateConverter(Double.class);
812         }
813         else if (targetClass == Byte.TYPE)
814         {
815             return internalCreateConverter(Byte.class);
816         }
817         else if (targetClass == Short.TYPE)
818         {
819             return internalCreateConverter(Short.class);
820         }
821         else if (targetClass == Integer.TYPE)
822         {
823             return internalCreateConverter(Integer.class);
824         }
825         else if (targetClass == Float.TYPE)
826         {
827             return internalCreateConverter(Float.class);
828         }
829         else if (targetClass == Character.TYPE)
830         {
831             return internalCreateConverter(Character.class);
832         }
833 
834         // Locate a Converter registered for the superclass (if any) of the
835         // target class,
836         // recursively working up the inheritance hierarchy.
837         Class superClazz = targetClass.getSuperclass();
838 
839         return superClazz != null ? internalCreateConverter(superClazz) : null;
840 
841     }
842 
843     private void setConverterProperties(final Class converterClass, final Converter converter)
844     {
845         final org.apache.myfaces.config.impl.digester.elements.Converter converterConfig = _runtimeConfig
846                 .getConverterConfiguration(converterClass.getName());
847 
848         if (converterConfig != null)
849         {
850 
851             final Iterator it = converterConfig.getProperties();
852 
853             while (it.hasNext())
854             {
855                 final Property property = (Property) it.next();
856 
857                 try
858                 {
859                     BeanUtils.setProperty(converter, property.getPropertyName(), property.getDefaultValue());
860                 }
861                 catch (Throwable th)
862                 {
863                     log.error("Initializing converter : " + converterClass.getName() + " with property : "
864                             + property.getPropertyName() + " and value : " + property.getDefaultValue() + " failed.");
865                 }
866             }
867         }
868     }
869 
870     // Note: this method used to be synchronized in the JSF 1.1 version. Why?
871     /**
872      * @deprecated
873      */
874     @Deprecated
875     @Override
876     public final MethodBinding createMethodBinding(final String reference, Class[] params) throws ReferenceSyntaxException
877     {
878         checkNull(reference, "reference");
879         checkEmpty(reference, "reference");
880 
881         // TODO: this check should be performed by the expression factory. It is a requirement of the TCK
882         if (!(reference.startsWith("#{") && reference.endsWith("}")))
883         {
884             throw new ReferenceSyntaxException("Invalid method reference: '" + reference + "'");
885         }
886 
887         if (params == null)
888             params = new Class[0];
889 
890         MethodExpression methodExpression;
891 
892         try
893         {
894             methodExpression = getExpressionFactory().createMethodExpression(threadELContext(), reference,
895                     Object.class, params);
896         }
897         catch (ELException e)
898         {
899             throw new ReferenceSyntaxException(e);
900         }
901 
902         return new MethodExpressionToMethodBinding(methodExpression);
903     }
904 
905     @Override
906     public final Validator createValidator(final String validatorId) throws FacesException
907     {
908         checkNull(validatorId, "validatorId");
909         checkEmpty(validatorId, "validatorId");
910 
911         Class validatorClass = _validatorClassMap.get(validatorId);
912         if (validatorClass == null)
913         {
914             String message = "Unknown validator id '" + validatorId + "'.";
915             log.error(message);
916             throw new FacesException(message);
917         }
918 
919         try
920         {
921             return (Validator) validatorClass.newInstance();
922         }
923         catch (Exception e)
924         {
925             log.error("Could not instantiate validator " + validatorClass, e);
926             throw new FacesException("Could not instantiate validator: " + validatorClass, e);
927         }
928     }
929 
930     /**
931      * @deprecated
932      */
933     @Override
934     public final ValueBinding createValueBinding(final String reference) throws ReferenceSyntaxException
935     {
936         checkNull(reference, "reference");
937         checkEmpty(reference, "reference");
938 
939         ValueExpression valueExpression;
940 
941         try
942         {
943             valueExpression = getExpressionFactory().createValueExpression(threadELContext(), reference, Object.class);
944         }
945         catch (ELException e)
946         {
947             throw new ReferenceSyntaxException(e);
948         }
949 
950         return new ValueExpressionToValueBinding(valueExpression);
951     }
952 
953     // gets the elContext from the current FacesContext()
954     private final ELContext threadELContext()
955     {
956         return getFaceContext().getELContext();
957     }
958 
959     @Override
960     public final String getDefaultRenderKitId()
961     {
962         return _defaultRenderKitId;
963     }
964 
965     @Override
966     public final void setDefaultRenderKitId(final String defaultRenderKitId)
967     {
968         _defaultRenderKitId = defaultRenderKitId;
969     }
970 
971     @Override
972     public final StateManager getStateManager()
973     {
974         return _stateManager;
975     }
976 
977     @Override
978     public final void setStateManager(final StateManager stateManager)
979     {
980         _stateManager = stateManager;
981     }
982 
983     private void checkNull(final Object param, final String paramName)
984     {
985         if (param == null)
986         {
987             throw new NullPointerException(paramName + " can not be null.");
988         }
989     }
990 
991     private void checkEmpty(final String param, final String paramName)
992     {
993         if (param.length() == 0)
994         {
995             throw new NullPointerException("String " + paramName + " can not be empty.");
996         }
997     }
998 }