Source code: org/apache/myfaces/application/ApplicationImpl.java
1 /*
2 * Copyright 2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 package org.apache.myfaces.application;
17
18 import org.apache.myfaces.application.jsp.JspStateManagerImpl;
19 import org.apache.myfaces.application.jsp.JspViewHandlerImpl;
20 import org.apache.myfaces.el.MethodBindingImpl;
21 import org.apache.myfaces.el.PropertyResolverImpl;
22 import org.apache.myfaces.el.ValueBindingImpl;
23 import org.apache.myfaces.el.VariableResolverImpl;
24 import org.apache.myfaces.util.BiLevelCacheMap;
25 import org.apache.myfaces.util.ClassUtils;
26 import org.apache.myfaces.config.impl.digester.elements.Property;
27
28 import org.apache.commons.logging.Log;
29 import org.apache.commons.logging.LogFactory;
30 import org.apache.commons.beanutils.BeanUtils;
31
32 import javax.faces.FacesException;
33 import javax.faces.application.Application;
34 import javax.faces.application.NavigationHandler;
35 import javax.faces.application.StateManager;
36 import javax.faces.application.ViewHandler;
37 import javax.faces.component.UIComponent;
38 import javax.faces.context.FacesContext;
39 import javax.faces.convert.Converter;
40 import javax.faces.el.*;
41 import javax.faces.event.ActionListener;
42 import javax.faces.validator.Validator;
43 import java.util.*;
44
45
46 /**
47 * DOCUMENT ME!
48 * @author Manfred Geiler (latest modification by $Author: baranda $)
49 * @author Anton Koinov
50 * @author Thomas Spiegl
51 * @version $Revision: 267274 $ $Date: 2005-09-02 14:53:14 -0400 (Fri, 02 Sep 2005) $
52 */
53 public class ApplicationImpl
54 extends Application
55 {
56 private static final Log log = LogFactory.getLog(ApplicationImpl.class);
57
58 //~ Instance fields ----------------------------------------------------------------------------
59
60 private final Map _valueBindingCache =
61 new BiLevelCacheMap(90)
62 {
63 protected Object newInstance(Object key)
64 {
65 return new ValueBindingImpl(ApplicationImpl.this, (String) key);
66 }
67 };
68
69 private Collection _supportedLocales = Collections.EMPTY_SET;
70 private Locale _defaultLocale;
71 private String _messageBundle;
72
73 private ViewHandler _viewHandler;
74 private NavigationHandler _navigationHandler;
75 private VariableResolver _variableResolver;
76 private PropertyResolver _propertyResolver;
77 private ActionListener _actionListener;
78 private String _defaultRenderKitId;
79 private StateManager _stateManager;
80
81 // components, converters, and validators can be added at runtime--must synchronize
82 private final Map _converterIdToClassMap = Collections.synchronizedMap(new HashMap());
83 private final Map _converterClassNameToClassMap = Collections.synchronizedMap(new HashMap());
84 private final Map _converterClassNameToConfigurationMap = Collections.synchronizedMap(new HashMap());
85 private final Map _componentClassMap = Collections.synchronizedMap(new HashMap());
86 private final Map _validatorClassMap = Collections.synchronizedMap(new HashMap());
87
88
89 //~ Constructors -------------------------------------------------------------------------------
90
91 public ApplicationImpl()
92 {
93 // set default implementation in constructor
94 // pragmatic approach, no syncronizing will be needed in get methods
95 _viewHandler = new JspViewHandlerImpl();
96 _navigationHandler = new NavigationHandlerImpl();
97 _variableResolver = new VariableResolverImpl();
98 _propertyResolver = new PropertyResolverImpl();
99 _actionListener = new ActionListenerImpl();
100 _defaultRenderKitId = "HTML_BASIC";
101 _stateManager = new JspStateManagerImpl();
102 if (log.isTraceEnabled()) log.trace("New Application instance created");
103 }
104
105 //~ Methods ------------------------------------------------------------------------------------
106
107 public void setActionListener(ActionListener actionListener)
108 {
109 if (actionListener == null)
110 {
111 log.error("setting actionListener to null is not allowed");
112 throw new NullPointerException("setting actionListener to null is not allowed");
113 }
114 _actionListener = actionListener;
115 if (log.isTraceEnabled()) log.trace("set actionListener = " + actionListener.getClass().getName());
116 }
117
118 public ActionListener getActionListener()
119 {
120 return _actionListener;
121 }
122
123 public Iterator getComponentTypes()
124 {
125 return _componentClassMap.keySet().iterator();
126 }
127
128 public Iterator getConverterIds()
129 {
130 return _converterIdToClassMap.keySet().iterator();
131 }
132
133 public Iterator getConverterTypes()
134 {
135 return _converterClassNameToClassMap.keySet().iterator();
136 }
137
138 public void setDefaultLocale(Locale locale)
139 {
140 if (locale == null)
141 {
142 log.error("setting locale to null is not allowed");
143 throw new NullPointerException("setting locale to null is not allowed");
144 }
145 _defaultLocale = locale;
146 if (log.isTraceEnabled()) log.trace("set defaultLocale = " + locale.getCountry() + " " + locale.getLanguage());
147 }
148
149 public Locale getDefaultLocale()
150 {
151 return _defaultLocale;
152 }
153
154 public void setMessageBundle(String messageBundle)
155 {
156 if (messageBundle == null)
157 {
158 log.error("setting messageBundle to null is not allowed");
159 throw new NullPointerException("setting messageBundle to null is not allowed");
160 }
161 _messageBundle = messageBundle;
162 if (log.isTraceEnabled()) log.trace("set MessageBundle = " + messageBundle);
163 }
164
165 public String getMessageBundle()
166 {
167 return _messageBundle;
168 }
169
170 public void setNavigationHandler(NavigationHandler navigationHandler)
171 {
172 if (navigationHandler == null)
173 {
174 log.error("setting navigationHandler to null is not allowed");
175 throw new NullPointerException("setting navigationHandler to null is not allowed");
176 }
177 _navigationHandler = navigationHandler;
178 if (log.isTraceEnabled()) log.trace("set NavigationHandler = " + navigationHandler.getClass().getName());
179 }
180
181 public NavigationHandler getNavigationHandler()
182 {
183 return _navigationHandler;
184 }
185
186 public void setPropertyResolver(PropertyResolver propertyResolver)
187 {
188 if (propertyResolver == null)
189 {
190 log.error("setting propertyResolver to null is not allowed");
191 throw new NullPointerException("setting propertyResolver to null is not allowed");
192 }
193 _propertyResolver = propertyResolver;
194 if (log.isTraceEnabled()) log.trace("set PropertyResolver = " + propertyResolver.getClass().getName());
195 }
196
197 public PropertyResolver getPropertyResolver()
198 {
199 return _propertyResolver;
200 }
201
202 public void setSupportedLocales(Collection locales)
203 {
204 if (locales == null)
205 {
206 log.error("setting supportedLocales to null is not allowed");
207 throw new NullPointerException("setting supportedLocales to null is not allowed");
208 }
209 _supportedLocales = locales;
210 if (log.isTraceEnabled()) log.trace("set SupportedLocales");
211 }
212
213 public Iterator getSupportedLocales()
214 {
215 return _supportedLocales.iterator();
216 }
217
218 public Iterator getValidatorIds()
219 {
220 return _validatorClassMap.keySet().iterator();
221 }
222
223 public void setVariableResolver(VariableResolver variableResolver)
224 {
225 if (variableResolver == null)
226 {
227 log.error("setting variableResolver to null is not allowed");
228 throw new NullPointerException("setting variableResolver to null is not allowed");
229 }
230 _variableResolver = variableResolver;
231 if (log.isTraceEnabled()) log.trace("set VariableResolver = " + variableResolver.getClass().getName());
232 }
233
234 public VariableResolver getVariableResolver()
235 {
236 return _variableResolver;
237 }
238
239 public void setViewHandler(ViewHandler viewHandler)
240 {
241 if (viewHandler == null)
242 {
243 log.error("setting viewHandler to null is not allowed");
244 throw new NullPointerException("setting viewHandler to null is not allowed");
245 }
246 _viewHandler = viewHandler;
247 if (log.isTraceEnabled()) log.trace("set ViewHandler = " + viewHandler.getClass().getName());
248 }
249
250 public ViewHandler getViewHandler()
251 {
252 return _viewHandler;
253 }
254
255 public void addComponent(String componentType, String componentClassName)
256 {
257 if ((componentType == null) || (componentType.length() == 0))
258 {
259 log.error("addComponent: componentType = null is not allowed");
260 throw new NullPointerException("addComponent: componentType = null ist not allowed");
261 }
262 if ((componentClassName == null) || (componentClassName.length() == 0))
263 {
264 log.error("addComponent: component = null is not allowed");
265 throw new NullPointerException("addComponent: component = null is not allowed");
266 }
267
268 try
269 {
270 _componentClassMap.put(componentType, ClassUtils.simpleClassForName(componentClassName));
271 if (log.isTraceEnabled()) log.trace("add Component class = " + componentClassName +
272 " for type = " + componentType);
273 }
274 catch (Exception e)
275 {
276 log.error("Component class " + componentClassName + " not found", e);
277 }
278 }
279
280 public void addConverter(String converterId, String converterClass)
281 {
282 if ((converterId == null) || (converterId.length() == 0))
283 {
284 log.error("addConverter: converterId = null is not allowed");
285 throw new NullPointerException("addConverter: converterId = null ist not allowed");
286 }
287 if ((converterClass == null) || (converterClass.length() == 0))
288 {
289 log.error("addConverter: converterClass = null is not allowed");
290 throw new NullPointerException("addConverter: converterClass = null ist not allowed");
291 }
292
293
294 try
295 {
296 _converterIdToClassMap.put(converterId, ClassUtils.simpleClassForName(converterClass));
297 if (log.isTraceEnabled()) log.trace("add Converter id = " + converterId +
298 " converterClass = " + converterClass);
299 }
300 catch (Exception e)
301 {
302 log.error("Converter class " + converterClass + " not found", e);
303 }
304 }
305
306 public void addConverter(Class targetClass, String converterClass)
307 {
308 if ((targetClass == null))
309 {
310 log.error("addConverter: targetClass = null is not allowed");
311 throw new NullPointerException("addConverter: targetClass = null ist not allowed");
312 }
313 if ((converterClass == null) || (converterClass.length() == 0))
314 {
315 log.error("addConverter: converterClass = null is not allowed");
316 throw new NullPointerException("addConverter: converterClass = null ist not allowed");
317 }
318
319 try
320 {
321 _converterClassNameToClassMap.put(targetClass, converterClass);
322 if (log.isTraceEnabled()) log.trace("add Converter for class = " + targetClass +
323 " converterClass = " + converterClass);
324 }
325 catch (Exception e)
326 {
327 log.error("Converter class " + converterClass + " not found", e);
328 }
329 }
330
331 public void addConverterConfiguration(String converterClassName,
332 org.apache.myfaces.config.impl.digester.elements.Converter configuration)
333 {
334 if ((converterClassName == null) || (converterClassName.length() == 0))
335 {
336 log.error("addConverterConfiguration: converterClassName = null is not allowed");
337 throw new NullPointerException("addConverterConfiguration: converterClassName = null ist not allowed");
338 }
339 if ((configuration == null))
340 {
341 log.error("addConverterConfiguration: configuration = null is not allowed");
342 throw new NullPointerException("addConverterConfiguration: configuration = null ist not allowed");
343 }
344
345 _converterClassNameToConfigurationMap.put(converterClassName, configuration);
346 }
347
348 public void addValidator(String validatorId, String validatorClass)
349 {
350 if ((validatorId == null) || (validatorId.length() == 0))
351 {
352 log.error("addValidator: validatorId = null is not allowed");
353 throw new NullPointerException("addValidator: validatorId = null ist not allowed");
354 }
355 if ((validatorClass == null) || (validatorClass.length() == 0))
356 {
357 log.error("addValidator: validatorClass = null is not allowed");
358 throw new NullPointerException("addValidator: validatorClass = null ist not allowed");
359 }
360
361 try
362 {
363 _validatorClassMap.put(validatorId, ClassUtils.simpleClassForName(validatorClass));
364 if (log.isTraceEnabled()) log.trace("add Validator id = " + validatorId +
365 " class = " + validatorClass);
366 }
367 catch (Exception e)
368 {
369 log.error("Validator class " + validatorClass + " not found", e);
370 }
371 }
372
373 public UIComponent createComponent(String componentType)
374 throws FacesException
375 {
376 if ((componentType == null) || (componentType.length() == 0))
377 {
378 log.error("createComponent: componentType = null is not allowed");
379 throw new NullPointerException("createComponent: componentType = null is not allowed");
380 }
381
382 Class componentClass;
383 synchronized (_componentClassMap)
384 {
385 componentClass = (Class) _componentClassMap.get(componentType);
386 }
387 if (componentClass == null)
388 {
389 log.error("Undefined component type " + componentType);
390 throw new FacesException("Undefined component type " + componentType);
391 }
392
393 try
394 {
395 return (UIComponent) componentClass.newInstance();
396 }
397 catch (Exception e)
398 {
399 log.error("Could not instantiate component componentType = " + componentType, e);
400 throw new FacesException("Could not instantiate component componentType = " + componentType, e);
401 }
402 }
403
404 public UIComponent createComponent(ValueBinding valueBinding,
405 FacesContext facesContext,
406 String componentType)
407 throws FacesException
408 {
409 if ((valueBinding == null))
410 {
411 log.error("createComponent: valueBinding = null is not allowed");
412 throw new NullPointerException("createComponent: valueBinding = null ist not allowed");
413 }
414 if ((facesContext == null))
415 {
416 log.error("createComponent: facesContext = null is not allowed");
417 throw new NullPointerException("createComponent: facesContext = null ist not allowed");
418 }
419 if ((componentType == null) || (componentType.length() == 0))
420 {
421 log.error("createComponent: componentType = null is not allowed");
422 throw new NullPointerException("createComponent: componentType = null ist not allowed");
423 }
424
425 Object obj = valueBinding.getValue(facesContext);
426 if (obj instanceof UIComponent)
427 {
428 return (UIComponent) obj;
429 }
430 else
431 {
432 UIComponent component = createComponent(componentType);
433 valueBinding.setValue(facesContext, component);
434 return component;
435 }
436 }
437
438 public Converter createConverter(String converterId)
439 {
440 if ((converterId == null) || (converterId.length() == 0))
441 {
442 log.error("createConverter: converterId = null is not allowed");
443 throw new NullPointerException("createConverter: converterId = null ist not allowed");
444 }
445
446 Class converterClass = (Class) _converterIdToClassMap.get(converterId);
447
448 try
449 {
450 Converter converter= (Converter) converterClass.newInstance();
451
452 setConverterProperties(converterClass, converter);
453
454 return converter;
455 }
456 catch (Exception e)
457 {
458 log.error("Could not instantiate converter " + converterClass, e);
459 throw new FacesException("Could not instantiate converter: " + converterClass, e);
460 }
461 }
462
463
464 public Converter createConverter(Class targetClass)
465 {
466 if (targetClass == null)
467 {
468 log.error("createConverter: targetClass = null is not allowed");
469 throw new NullPointerException("createConverter: targetClass = null ist not allowed");
470 }
471
472 Converter converter = internalCreateConverter(targetClass);
473
474 return converter;
475 }
476
477
478 private Converter internalCreateConverter(Class targetClass)
479 {
480 // Locate a Converter registered for the target class itself.
481 String converterClassName = (String)_converterClassNameToClassMap.get(targetClass);
482
483 //Locate a Converter registered for interfaces that are
484 // implemented by the target class (directly or indirectly).
485 if (converterClassName == null)
486 {
487 Class interfaces[] = targetClass.getInterfaces();
488 if (interfaces != null)
489 {
490 for (int i = 0, len = interfaces.length; i < len; i++)
491 {
492 // search all superinterfaces for a matching converter, create it
493 Converter converter = internalCreateConverter(interfaces[i]);
494 if (converter != null)
495 {
496 return converter;
497 }
498 }
499 }
500 }
501
502 if (converterClassName != null)
503 {
504 try
505 {
506 Class converterClass = ClassUtils.simpleClassForName(converterClassName);
507
508 Converter converter = (Converter) converterClass.newInstance();
509
510 setConverterProperties(converterClass, converter);
511
512 return converter;
513 }
514 catch (Exception e)
515 {
516 log.error("Could not instantiate converter " + converterClassName, e);
517 throw new FacesException("Could not instantiate converter: " + converterClassName, e);
518 }
519 }
520
521 // locate converter for primitive types
522 if (targetClass == Long.TYPE)
523 {
524 return internalCreateConverter(Long.class);
525 } else if (targetClass == Boolean.TYPE)
526 {
527 return internalCreateConverter(Boolean.class);
528 } else if (targetClass == Double.TYPE)
529 {
530 return internalCreateConverter(Double.class);
531 } else if (targetClass == Byte.TYPE)
532 {
533 return internalCreateConverter(Byte.class);
534 } else if (targetClass == Short.TYPE)
535 {
536 return internalCreateConverter(Short.class);
537 } else if (targetClass == Integer.TYPE)
538 {
539 return internalCreateConverter(Integer.class);
540 } else if (targetClass == Float.TYPE)
541 {
542 return internalCreateConverter(Float.class);
543 } else if (targetClass == Character.TYPE)
544 {
545 return internalCreateConverter(Character.class);
546 }
547
548
549 //Locate a Converter registered for the superclass (if any) of the target class,
550 // recursively working up the inheritance hierarchy.
551 Class superClazz = targetClass.getSuperclass();
552 if (superClazz != null)
553 {
554 return internalCreateConverter(superClazz);
555 }
556 else
557 {
558 return null;
559 }
560
561 }
562
563 private void setConverterProperties(Class converterClass, Converter converter)
564 {
565 org.apache.myfaces.config.impl.digester.elements.Converter converterConfig =
566 (org.apache.myfaces.config.impl.digester.elements.Converter)
567 _converterClassNameToConfigurationMap.get(converterClass.getName());
568
569 if(converterConfig != null)
570 {
571
572 Iterator it = converterConfig.getProperties();
573
574 while (it.hasNext())
575 {
576 Property property = (Property) it.next();
577
578 try
579 {
580 BeanUtils.setProperty(converter,property.getPropertyName(),property.getDefaultValue());
581 }
582 catch(Throwable th)
583 {
584 log.error("Initializing converter : "+converterClass.getName()+" with property : "+
585 property.getPropertyName()+" and value : "+property.getDefaultValue()+" failed.");
586 }
587 }
588 }
589 }
590
591
592 public synchronized MethodBinding createMethodBinding(String reference, Class[] params)
593 throws ReferenceSyntaxException
594 {
595 if ((reference == null) || (reference.length() == 0))
596 {
597 log.error("createMethodBinding: reference = null is not allowed");
598 throw new NullPointerException("createMethodBinding: reference = null ist not allowed");
599 }
600
601 // We choose to instantiate a new MethodBinding every time as this is much easier
602 // and about as efficient as implementing a cache specifically for MethodBinding,
603 // which is complicated by the need to use a conposite key=(reference, params)
604 // (significant part of MethodBinding is already cached by ValueBinding implicitly)
605 return new MethodBindingImpl(this, reference, params);
606 }
607
608 public Validator createValidator(String validatorId) throws FacesException
609 {
610 if ((validatorId == null) || (validatorId.length() == 0))
611 {
612 log.error("createValidator: validatorId = null is not allowed");
613 throw new NullPointerException("createValidator: validatorId = null ist not allowed");
614 }
615
616 Class validatorClass = (Class) _validatorClassMap.get(validatorId);
617 if (validatorClass == null)
618 {
619 String message = "Unknown validator id '" + validatorId + "'.";
620 log.error(message);
621 throw new FacesException(message);
622 }
623
624 try
625 {
626 return (Validator) validatorClass.newInstance();
627 }
628 catch (Exception e)
629 {
630 log.error("Could not instantiate validator " + validatorClass, e);
631 throw new FacesException("Could not instantiate validator: " + validatorClass, e);
632 }
633 }
634
635 public ValueBinding createValueBinding(String reference) throws ReferenceSyntaxException
636 {
637 if ((reference == null) || (reference.length() == 0))
638 {
639 log.error("createValueBinding: reference = null is not allowed");
640 throw new NullPointerException("createValueBinding: reference = null is not allowed");
641 }
642 return (ValueBinding) _valueBindingCache.get(reference);
643 }
644
645
646 public String getDefaultRenderKitId()
647 {
648 return _defaultRenderKitId;
649 }
650
651 public void setDefaultRenderKitId(String defaultRenderKitId)
652 {
653 _defaultRenderKitId = defaultRenderKitId;
654 }
655
656 public StateManager getStateManager()
657 {
658 return _stateManager;
659 }
660
661 public void setStateManager(StateManager stateManager)
662 {
663 _stateManager = stateManager;
664 }
665 }