1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.myfaces.shared.renderkit;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.FileNotFoundException;
23 import java.io.IOException;
24 import java.io.InputStream;
25 import java.io.Serializable;
26 import java.lang.reflect.Array;
27 import java.util.ArrayList;
28 import java.util.Collections;
29 import java.util.Date;
30 import java.util.HashSet;
31 import java.util.Iterator;
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35
36 import javax.el.ValueExpression;
37 import javax.faces.FacesException;
38 import javax.faces.FactoryFinder;
39 import javax.faces.component.EditableValueHolder;
40 import javax.faces.component.NamingContainer;
41 import javax.faces.component.UIComponent;
42 import javax.faces.component.UIForm;
43 import javax.faces.component.UIInput;
44 import javax.faces.component.UINamingContainer;
45 import javax.faces.component.UIOutput;
46 import javax.faces.component.UISelectMany;
47 import javax.faces.component.UISelectOne;
48 import javax.faces.component.UIViewRoot;
49 import javax.faces.component.ValueHolder;
50 import javax.faces.component.html.HtmlInputText;
51 import javax.faces.context.FacesContext;
52 import javax.faces.convert.Converter;
53 import javax.faces.convert.ConverterException;
54 import javax.faces.el.PropertyNotFoundException;
55 import javax.faces.el.ValueBinding;
56 import javax.faces.event.PhaseId;
57 import javax.faces.model.SelectItem;
58 import javax.faces.render.RenderKit;
59 import javax.faces.render.RenderKitFactory;
60 import javax.faces.render.ResponseStateManager;
61
62 import org.apache.commons.logging.Log;
63 import org.apache.commons.logging.LogFactory;
64 import org.apache.myfaces.shared.renderkit.html.util.FormInfo;
65 import org.apache.myfaces.shared.util.HashMapUtils;
66 import org.apache.myfaces.shared.util.SelectItemsIterator;
67
68 /***
69 * @author Manfred Geiler (latest modification by $Author: matzew $)
70 * @version $Revision: 807542 $ $Date: 2009-08-25 05:22:20 -0500 (Tue, 25 Aug 2009) $
71 */
72 public final class RendererUtils
73 {
74 private RendererUtils(){
75
76 }
77
78 private static final Log log = LogFactory.getLog(RendererUtils.class);
79
80 public static final String SELECT_ITEM_LIST_ATTR = RendererUtils.class.getName() + ".LIST";
81 public static final String EMPTY_STRING = "";
82 public static final Object NOTHING = new Serializable() {
83 public boolean equals(final Object o)
84 {
85 if (o != null)
86 {
87 if (o.getClass().equals(this.getClass()))
88 {
89 return true;
90 }
91 }
92 return false;
93 }
94 };
95
96 public static final String ACTION_FOR_LIST = "org.apache.myfaces.ActionForList";
97 public static final String ACTION_FOR_PHASE_LIST = "org.apache.myfaces.ActionForPhaseList";
98
99 public static final String SEQUENCE_PARAM = "jsf_sequence";
100
101 private static final String RENDER_KIT_IMPL = RendererUtils.class.getName() + ".RenderKitImpl";
102
103 public static String getPathToComponent(UIComponent component)
104 {
105 StringBuffer buf = new StringBuffer();
106
107 if(component == null)
108 {
109 buf.append("{Component-Path : ");
110 buf.append("[null]}");
111 return buf.toString();
112 }
113
114 getPathToComponent(component,buf);
115
116 buf.insert(0,"{Component-Path : ");
117 buf.append("}");
118
119 return buf.toString();
120 }
121
122 private static void getPathToComponent(UIComponent component, StringBuffer buf)
123 {
124 if(component == null)
125 return;
126
127 StringBuffer intBuf = new StringBuffer();
128
129 intBuf.append("[Class: ");
130 intBuf.append(component.getClass().getName());
131 if(component instanceof UIViewRoot)
132 {
133 intBuf.append(",ViewId: ");
134 intBuf.append(((UIViewRoot) component).getViewId());
135 }
136 else
137 {
138 intBuf.append(",Id: ");
139 intBuf.append(component.getId());
140 }
141 intBuf.append("]");
142
143 buf.insert(0,intBuf.toString());
144
145 getPathToComponent(component.getParent(), buf);
146 }
147
148 public static String getConcatenatedId(FacesContext context, UIComponent container,
149 String clientId)
150 {
151 UIComponent child = container.findComponent(clientId);
152
153 if(child == null)
154 return clientId;
155
156 return getConcatenatedId(context, child);
157 }
158
159 public static String getConcatenatedId(FacesContext context, UIComponent component)
160 {
161 if (context == null) throw new NullPointerException("context");
162
163 StringBuffer idBuf = new StringBuffer();
164
165 idBuf.append(component.getId());
166
167 UIComponent parent;
168
169 while((parent = component.getParent())!=null)
170 {
171 if(parent instanceof NamingContainer)
172 {
173 idBuf.insert(0,NamingContainer.SEPARATOR_CHAR);
174 idBuf.insert(0,parent.getId());
175 }
176 }
177
178 return idBuf.toString();
179 }
180
181 public static Boolean getBooleanValue(UIComponent component)
182 {
183 Object value = getObjectValue(component);
184
185 if (value instanceof String) {
186 value = Boolean.valueOf((String)value);
187 }
188
189 if (value==null || value instanceof Boolean)
190 {
191 return (Boolean) value;
192 }
193
194 throw new IllegalArgumentException("Expected submitted value of type Boolean for Component : "+
195 getPathToComponent(component));
196
197 }
198
199 public static Date getDateValue(UIComponent component)
200 {
201 Object value = getObjectValue(component);
202 if (value==null || value instanceof Date)
203 {
204 return (Date) value;
205 }
206
207 throw new IllegalArgumentException("Expected submitted value of type Date for component : "
208 +getPathToComponent(component));
209 }
210
211 public static Object getObjectValue(UIComponent component)
212 {
213 if (!(component instanceof ValueHolder))
214 {
215 throw new IllegalArgumentException("Component : "+
216 getPathToComponent(component)+"is not a ValueHolder");
217 }
218
219 if (component instanceof EditableValueHolder)
220 {
221 Object value = ((EditableValueHolder)component).getSubmittedValue();
222 if(value != null && !NOTHING.equals(value))
223 {
224 return value;
225 }
226 }
227
228 return ((ValueHolder)component).getValue();
229 }
230
231 @Deprecated
232 public static String getStringValue(FacesContext context, ValueBinding vb)
233 {
234 Object value = vb.getValue(context);
235 if (value != null)
236 {
237 return value.toString();
238 }
239 return null;
240 }
241
242 public static String getStringValue(FacesContext context, ValueExpression ve)
243 {
244 Object value = ve.getValue(context.getELContext());
245 if (value != null)
246 {
247 return value.toString();
248 }
249 return null;
250 }
251
252 public static String getStringValue(FacesContext facesContext,
253 UIComponent component)
254 {
255 try
256 {
257 if (!(component instanceof ValueHolder))
258 {
259 throw new IllegalArgumentException("Component : "+getPathToComponent(component)+"is not a ValueHolder");
260 }
261
262 if (component instanceof EditableValueHolder)
263 {
264 Object submittedValue = ((EditableValueHolder)component).getSubmittedValue();
265 if (submittedValue != null)
266 {
267 if (submittedValue instanceof String)
268 {
269 if (log.isDebugEnabled()) log.debug("returning 1 '" + submittedValue + "'");
270 return (String)submittedValue;
271 }
272
273 throw new IllegalArgumentException("Expected submitted value of type String for component : "
274 +getPathToComponent(component));
275 }
276 }
277
278 Object value;
279
280 if(component instanceof EditableValueHolder) {
281
282 EditableValueHolder holder = (EditableValueHolder) component;
283
284 if(holder.isLocalValueSet()) {
285 value = holder.getLocalValue();
286 } else {
287 value = getValue(component);
288 }
289 }
290 else {
291 value = getValue(component);
292 }
293
294 Converter converter = ((ValueHolder)component).getConverter();
295 if (converter == null && value != null)
296 {
297
298 try
299 {
300 converter = facesContext.getApplication().createConverter(value.getClass());
301 if (log.isDebugEnabled()) log.debug("the created converter is " + converter);
302 }
303 catch (FacesException e)
304 {
305 log.error("No converter for class " + value.getClass().getName() + " found (component id=" + component.getId() + ").");
306
307 }
308 }
309
310 if (converter == null)
311 {
312 if (value == null)
313 {
314 if (log.isDebugEnabled()) log.debug("returning an empty string");
315 return "";
316 }
317
318 if (log.isDebugEnabled()) log.debug("returning an .toString");
319 return value.toString();
320
321 }
322
323 if (log.isDebugEnabled()) log.debug("returning converter get as string " + converter);
324 return converter.getAsString(facesContext, component, value);
325
326 }
327 catch(PropertyNotFoundException ex)
328 {
329 log.error("Property not found - called by component : "+getPathToComponent(component),ex);
330
331 throw ex;
332 }
333 }
334
335 private static Object getValue(UIComponent component) {
336 Object value;
337 try
338 {
339 value = ((ValueHolder) component).getValue();
340 }
341 catch(Exception ex)
342 {
343 throw new FacesException("Could not retrieve value of component with path : "+
344 getPathToComponent(component),ex);
345 }
346 return value;
347 }
348
349 /***
350 * See JSF Spec. 8.5 Table 8-1
351 * @param value
352 * @return boolean
353 */
354 public static boolean isDefaultAttributeValue(Object value)
355 {
356 if (value == null)
357 {
358 return true;
359 }
360 else if (value instanceof Boolean)
361 {
362 return !((Boolean) value).booleanValue();
363 }
364 else if (value instanceof Number)
365 {
366 if (value instanceof Integer)
367 {
368 return ((Number)value).intValue() == Integer.MIN_VALUE;
369 }
370 else if (value instanceof Double)
371 {
372 return ((Number)value).doubleValue() == Double.MIN_VALUE;
373 }
374 else if (value instanceof Long)
375 {
376 return ((Number)value).longValue() == Long.MIN_VALUE;
377 }
378 else if (value instanceof Byte)
379 {
380 return ((Number)value).byteValue() == Byte.MIN_VALUE;
381 }
382 else if (value instanceof Float)
383 {
384 return ((Number)value).floatValue() == Float.MIN_VALUE;
385 }
386 else if (value instanceof Short)
387 {
388 return ((Number)value).shortValue() == Short.MIN_VALUE;
389 }
390 }
391 return false;
392 }
393
394 /***
395 * Find the proper Converter for the given UIOutput component.
396 * @return the Converter or null if no Converter specified or needed
397 * @throws FacesException if the Converter could not be created
398 */
399 public static Converter findUIOutputConverter(FacesContext facesContext,
400 UIOutput component)
401 throws FacesException
402 {
403 return _SharedRendererUtils.findUIOutputConverter(facesContext, component);
404 }
405
406
407 /***
408 * Find proper Converter for the entries in the associated List or Array of
409 * the given UISelectMany as specified in API Doc of UISelectMany.
410 * @return the Converter or null if no Converter specified or needed
411 * @throws FacesException if the Converter could not be created
412 */
413 public static Converter findUISelectManyConverter(FacesContext facesContext,
414 UISelectMany component)
415 {
416 Converter converter = component.getConverter();
417 if (converter != null) return converter;
418
419
420 ValueExpression vb = component.getValueExpression("value");
421 if (vb == null) return null;
422
423
424
425
426 Class valueType = null;
427 Object value = vb.getValue(facesContext.getELContext());
428 valueType = (value != null) ? value.getClass() :
429 vb.getType(facesContext.getELContext()) ;
430
431 if (valueType == null) return null;
432
433 if (List.class.isAssignableFrom(valueType))
434 {
435
436
437
438
439
440
441
442
443 List selectItems = RendererUtils.internalGetSelectItemList(component);
444
445 if (selectItems != null && selectItems.size() > 0)
446 {
447 SelectItem selectItem = (SelectItem) selectItems.get(0);
448 Class listComponentType = selectItem.getValue().getClass();
449
450 try
451 {
452 return facesContext.getApplication().createConverter(listComponentType);
453 }
454 catch (FacesException e)
455 {
456 log.error("No Converter for type " + listComponentType.getName() + " found", e);
457 return null;
458 }
459
460 }
461
462 return null;
463 }
464
465 if (!valueType.isArray())
466 {
467 throw new IllegalArgumentException("ValueBinding for UISelectMany : "+getPathToComponent(component)+" must be of type List or Array");
468 }
469
470 Class arrayComponentType = valueType.getComponentType();
471 if (String.class.equals(arrayComponentType)) return null;
472 if (Object.class.equals(arrayComponentType)) return null;
473
474 try
475 {
476 return facesContext.getApplication().createConverter(arrayComponentType);
477 }
478 catch (FacesException e)
479 {
480 log.error("No Converter for type " + arrayComponentType.getName() + " found", e);
481 return null;
482 }
483 }
484
485
486 public static void checkParamValidity(FacesContext facesContext, UIComponent uiComponent, Class compClass)
487 {
488 if(facesContext == null)
489 throw new NullPointerException("facesContext may not be null");
490 if(uiComponent == null)
491 throw new NullPointerException("uiComponent may not be null");
492
493
494
495 if (compClass != null && !(compClass.isInstance(uiComponent)))
496 {
497 throw new IllegalArgumentException("uiComponent : "+getPathToComponent(uiComponent)+
498 " is not instance of "+compClass.getName()+" as it should be");
499 }
500 }
501
502
503 public static void renderChildren(FacesContext facesContext, UIComponent component)
504 throws IOException
505 {
506 if (component.getChildCount() > 0)
507 {
508 for (Iterator it = component.getChildren().iterator(); it.hasNext(); )
509 {
510 UIComponent child = (UIComponent)it.next();
511 renderChild(facesContext, child);
512 }
513 }
514 }
515
516
517 public static void renderChild(FacesContext facesContext, UIComponent child)
518 throws IOException
519 {
520 if (!child.isRendered())
521 {
522 return;
523 }
524
525 child.encodeBegin(facesContext);
526 if (child.getRendersChildren())
527 {
528 child.encodeChildren(facesContext);
529 }
530 else
531 {
532 renderChildren(facesContext, child);
533 }
534 child.encodeEnd(facesContext);
535 }
536
537
538
539 /***
540 * @param uiSelectOne
541 * @return List of SelectItem Objects
542 */
543 public static List getSelectItemList(UISelectOne uiSelectOne)
544 {
545 return internalGetSelectItemList(uiSelectOne);
546 }
547
548 /***
549 * @param uiSelectMany
550 * @return List of SelectItem Objects
551 */
552 public static List getSelectItemList(UISelectMany uiSelectMany)
553 {
554 return internalGetSelectItemList(uiSelectMany);
555 }
556
557 private static List internalGetSelectItemList(UIComponent uiComponent)
558 {
559
560
561
562
563
564
565
566
567 List list = new ArrayList();
568
569 for (Iterator iter = new SelectItemsIterator(uiComponent); iter.hasNext();)
570 {
571 list.add(iter.next());
572 }
573 return list;
574 }
575
576
577 /***
578 * Convenient utility method that returns the currently submitted values of
579 * a UISelectMany component as a Set, of which the contains method can then be
580 * easily used to determine if a select item is currently selected.
581 * Calling the contains method of this Set with the renderable (String converted) item value
582 * as argument returns true if this item is selected.
583 * @param uiSelectMany
584 * @return Set containing all currently selected values
585 */
586 public static Set getSubmittedValuesAsSet(FacesContext context, UIComponent component, Converter converter, UISelectMany uiSelectMany)
587 {
588 Object submittedValues = uiSelectMany.getSubmittedValue();
589 if (submittedValues == null)
590 {
591 return null;
592 }
593
594 if(converter != null) {
595 converter = new PassThroughAsStringConverter(converter);
596 }
597
598 return internalSubmittedOrSelectedValuesAsSet(context, component, converter, uiSelectMany, submittedValues);
599 }
600
601
602 /***
603 * Convenient utility method that returns the currently selected values of
604 * a UISelectMany component as a Set, of which the contains method can then be
605 * easily used to determine if a value is currently selected.
606 * Calling the contains method of this Set with the item value
607 * as argument returns true if this item is selected.
608 * @param uiSelectMany
609 * @return Set containing all currently selected values
610 */
611 public static Set getSelectedValuesAsSet(FacesContext context, UIComponent component, Converter converter, UISelectMany uiSelectMany)
612 {
613 Object selectedValues = uiSelectMany.getValue();
614
615 return internalSubmittedOrSelectedValuesAsSet(context, component, converter, uiSelectMany, selectedValues);
616 }
617
618
619 /***
620 * Convenient utility method that returns the currently given value as String,
621 * using the given converter.
622 * Especially usefull for dealing with primitive types.
623 */
624 public static String getConvertedStringValue(FacesContext context,
625 UIComponent component, Converter converter, Object value) {
626 if (converter == null) {
627 if (value == null) {
628 return "";
629 } else if (value instanceof String) {
630 return (String) value;
631 } else if (RendererUtils.NOTHING.equals(value)) {
632 return "";
633 } else {
634 throw new IllegalArgumentException(
635 "Value is no String (class=" + value.getClass().getName() + ", value=" + value + ") and component "
636 + component.getClientId(context) +"with path: "
637 + getPathToComponent(component)
638 + " does not have a Converter");
639 }
640 }
641
642 if (RendererUtils.NOTHING.equals(value))
643 {
644 return converter.getAsString(context, component, "");
645 }
646 else
647 {
648 return converter.getAsString(context, component, value);
649 }
650 }
651
652
653 /***
654 * Convenient utility method that returns the currently given SelectItem value
655 * as String, using the given converter.
656 * Especially usefull for dealing with primitive types.
657 */
658 public static String getConvertedStringValue(FacesContext context,
659 UIComponent component, Converter converter, SelectItem selectItem) {
660 return getConvertedStringValue(context, component, converter, selectItem.getValue());
661 }
662
663
664 private static Set internalSubmittedOrSelectedValuesAsSet(FacesContext context,
665 UIComponent component, Converter converter, UISelectMany uiSelectMany,
666 Object values)
667 {
668 if (values == null || EMPTY_STRING.equals(values))
669 {
670 return Collections.EMPTY_SET;
671 }
672 else if (values instanceof Object[])
673 {
674
675 Object[] ar = (Object[])values;
676 if (ar.length == 0)
677 {
678 return Collections.EMPTY_SET;
679 }
680
681 HashSet set = new HashSet(HashMapUtils.calcCapacity(ar.length));
682 for (int i = 0; i < ar.length; i++)
683 {
684 set.add( getConvertedStringValue(context, component, converter, ar[i]) );
685 }
686 return set;
687 }
688 else if (values.getClass().isArray())
689 {
690
691 int len = Array.getLength(values);
692 HashSet set = new HashSet(org.apache.myfaces.shared.util.HashMapUtils.calcCapacity(len));
693 for (int i = 0; i < len; i++)
694 {
695 set.add( getConvertedStringValue(context, component, converter, Array.get(values,i)) );
696 }
697 return set;
698 }
699 else if (values instanceof List)
700 {
701 List lst = (List)values;
702 if (lst.size() == 0)
703 {
704 return Collections.EMPTY_SET;
705 }
706
707 HashSet set = new HashSet(HashMapUtils.calcCapacity(lst.size()));
708 for (Iterator i = lst.iterator(); i.hasNext();)
709 set.add(getConvertedStringValue(context, component, converter, i.next()));
710
711 return set;
712
713 }
714 else
715 {
716 throw new IllegalArgumentException("Value of UISelectMany component with path : "
717 + getPathToComponent(uiSelectMany) + " is not of type Array or List");
718 }
719 }
720
721 public static Object getConvertedUISelectOneValue(FacesContext facesContext, UISelectOne output, Object submittedValue){
722 if (submittedValue != null && !(submittedValue instanceof String))
723 {
724 if (RendererUtils.NOTHING.equals(submittedValue))
725 {
726 return null;
727 }
728 throw new IllegalArgumentException("Submitted value of type String for component : "
729 + getPathToComponent(output) + "expected");
730 }
731
732
733
734
735 if ((submittedValue != null) && (submittedValue instanceof String) && ("".equals(submittedValue)))
736 {
737
738 submittedValue = null;
739 }
740
741 Converter converter;
742 try
743 {
744 converter = findUIOutputConverter(facesContext, output);
745 }
746 catch (FacesException e)
747 {
748 throw new ConverterException(e);
749 }
750
751 return converter == null ? submittedValue : converter
752 .getAsObject(facesContext, output, (String) submittedValue);
753 }
754
755 public static Object getConvertedUIOutputValue(FacesContext facesContext, UIOutput output, Object submittedValue)
756 throws ConverterException
757 {
758 if (submittedValue != null && !(submittedValue instanceof String))
759 {
760 if (RendererUtils.NOTHING.equals(submittedValue))
761 {
762 return null;
763 }
764 throw new IllegalArgumentException("Submitted value of type String for component : "
765 + getPathToComponent(output) + "expected");
766 }
767
768 Converter converter;
769 try
770 {
771 converter = findUIOutputConverter(facesContext, output);
772 }
773 catch (FacesException e)
774 {
775 throw new ConverterException(e);
776 }
777
778 return converter == null ? submittedValue : converter
779 .getAsObject(facesContext, output, (String) submittedValue);
780 }
781
782 public static Object getConvertedUISelectManyValue(FacesContext facesContext, UISelectMany selectMany,
783 Object submittedValue) throws ConverterException
784 {
785 if (submittedValue == null)
786 {
787 return null;
788 }
789
790 if (!(submittedValue instanceof String[]))
791 {
792 throw new ConverterException("Submitted value of type String[] for component : "
793 + getPathToComponent(selectMany) + "expected");
794 }
795
796 return org.apache.myfaces.shared.renderkit._SharedRendererUtils.getConvertedUISelectManyValue(facesContext,
797 selectMany, (String[]) submittedValue);
798 }
799
800 public static boolean getBooleanAttribute(UIComponent component, String attrName, boolean defaultValue)
801 {
802 Boolean b = (Boolean) component.getAttributes().get(attrName);
803 return b != null ? b.booleanValue() : defaultValue;
804 }
805
806 public static int getIntegerAttribute(UIComponent component, String attrName, int defaultValue)
807 {
808 Integer i = (Integer) component.getAttributes().get(attrName);
809 return i != null ? i.intValue() : defaultValue;
810 }
811
812 private static final String TRINIDAD_FORM_COMPONENT_FAMILY = "org.apache.myfaces.trinidad.Form";
813 private static final String ADF_FORM_COMPONENT_FAMILY = "oracle.adf.Form";
814
815
816 /***
817 * Find the enclosing form of a component
818 * in the view-tree.
819 * All Subclasses of <code>UIForm</code> and all known
820 * form-families are searched for.
821 * Currently those are the Trinidad form family,
822 * and the (old) ADF Faces form family.
823 * <p/>
824 * There might be additional form families
825 * which have to be explicitly entered here.
826 *
827 * @param uiComponent
828 * @param facesContext
829 * @return FormInfo Information about the form - the form itself and its name.
830 */
831 public static FormInfo findNestingForm(UIComponent uiComponent, FacesContext facesContext)
832 {
833 UIComponent parent = uiComponent.getParent();
834 while (parent != null && (!ADF_FORM_COMPONENT_FAMILY.equals(parent.getFamily()) &&
835 !TRINIDAD_FORM_COMPONENT_FAMILY.equals(parent.getFamily()) &&
836 !(parent instanceof UIForm)))
837 {
838 parent = parent.getParent();
839 }
840
841 if (parent != null)
842 {
843
844 String formName = parent.getClientId(facesContext);
845 return new FormInfo(parent, formName);
846 }
847
848 return null;
849 }
850
851 public static boolean getBooleanValue(String attribute, Object value, boolean defaultValue) {
852 if (value instanceof Boolean) {
853 return ((Boolean) value).booleanValue();
854 }
855 else if (value instanceof String) {
856 return Boolean.valueOf((String) value).booleanValue();
857 }
858 else if (value != null) {
859 log.error("value for attribute " + attribute +
860 " must be instanceof 'Boolean' or 'String', is of type : " + value.getClass());
861
862 return defaultValue;
863 }
864
865 return defaultValue;
866 }
867
868 public static void copyHtmlInputTextAttributes(HtmlInputText src, HtmlInputText dest)
869 {
870 dest.setId(src.getId());
871 boolean forceId = getBooleanValue(
872 JSFAttr.FORCE_ID_ATTR,
873 src.getAttributes().get(JSFAttr.FORCE_ID_ATTR),
874 false);
875 if (forceId) {
876 dest.getAttributes().put(JSFAttr.FORCE_ID_ATTR, Boolean.TRUE);
877 }
878 dest.setImmediate(src.isImmediate());
879 dest.setTransient(src.isTransient());
880 dest.setAccesskey(src.getAccesskey());
881 dest.setAlt(src.getAlt());
882 dest.setConverter(src.getConverter());
883 dest.setDir(src.getDir());
884 dest.setDisabled(src.isDisabled());
885 dest.setLang(src.getLang());
886 dest.setLocalValueSet(src.isLocalValueSet());
887 dest.setMaxlength(src.getMaxlength());
888 dest.setOnblur(src.getOnblur());
889 dest.setOnchange(src.getOnchange());
890 dest.setOnclick(src.getOnclick());
891 dest.setOndblclick(src.getOndblclick());
892 dest.setOnfocus(src.getOnfocus());
893 dest.setOnkeydown(src.getOnkeydown());
894 dest.setOnkeypress(src.getOnkeypress());
895 dest.setOnkeyup(src.getOnkeyup());
896 dest.setOnmousedown(src.getOnmousedown());
897 dest.setOnmousemove(src.getOnmousemove());
898 dest.setOnmouseout(src.getOnmouseout());
899 dest.setOnmouseover(src.getOnmouseover());
900 dest.setOnmouseup(src.getOnmouseup());
901 dest.setOnselect(src.getOnselect());
902 dest.setReadonly(src.isReadonly());
903 dest.setRendered(src.isRendered());
904 dest.setRequired(src.isRequired());
905 dest.setSize(src.getSize());
906 dest.setStyle(src.getStyle());
907 dest.setStyleClass(src.getStyleClass());
908 dest.setTabindex(src.getTabindex());
909 dest.setTitle(src.getTitle());
910 dest.setValidator(src.getValidator());
911 }
912
913 public static Integer getViewSequence(FacesContext facescontext)
914 {
915 Map map = facescontext.getExternalContext().getRequestMap();
916 Integer sequence = (Integer) map.get(SEQUENCE_PARAM);
917 if (sequence == null)
918 {
919 sequence = new Integer(1);
920 map.put(SEQUENCE_PARAM, sequence);
921
922 synchronized (facescontext.getExternalContext().getSession(true))
923 {
924 facescontext.getExternalContext().getSessionMap().put(RendererUtils.SEQUENCE_PARAM, sequence);
925 }
926 }
927 return sequence;
928 }
929
930 public static UIComponent findComponent(UIComponent headerComp, Class clazz)
931 {
932 if (clazz.isAssignableFrom(headerComp.getClass()))
933 {
934 return headerComp;
935 }
936
937 List li = headerComp.getChildren();
938
939 for (int i = 0; i < li.size(); i++)
940 {
941 UIComponent comp = (UIComponent) li.get(i);
942
943
944 UIComponent lookupComp = findComponent(comp, clazz);
945
946 if (lookupComp != null)
947 return lookupComp;
948 }
949
950 return null;
951 }
952
953 public static void addOrReplaceChild(UIInput component, UIComponent child)
954 {
955 List li = component.getChildren();
956
957 for (int i = 0; i < li.size(); i++)
958 {
959 UIComponent oldChild = (UIComponent) li.get(i);
960
961 if (oldChild.getId() != null && oldChild.getId().equals(child.getId()))
962 {
963 li.set(i, child);
964 return;
965 }
966 }
967
968 component.getChildren().add(child);
969 }
970
971 public static String getClientId(FacesContext facesContext, UIComponent uiComponent, String forAttr)
972 {
973 UIComponent forComponent = uiComponent.findComponent(forAttr);
974 if (forComponent == null)
975 {
976 if (log.isInfoEnabled())
977 {
978 log
979 .info("Unable to find component '"
980 + forAttr
981 + "' (calling findComponent on component '"
982 + uiComponent.getClientId(facesContext)
983 + "')."
984 + " We'll try to return a guessed client-id anyways -"
985 + " this will be a problem if you put the referenced component"
986 + " into a different naming-container. If this is the case, you can always use the full client-id.");
987 }
988 if (forAttr.length() > 0 && forAttr.charAt(0) == UINamingContainer.SEPARATOR_CHAR)
989 {
990
991 return forAttr.substring(1);
992 }
993
994
995 String labelClientId = uiComponent.getClientId(facesContext);
996 int colon = labelClientId.lastIndexOf(UINamingContainer.SEPARATOR_CHAR);
997
998 return colon == -1 ? forAttr : labelClientId.substring(0, colon + 1) + forAttr;
999
1000 }
1001
1002 return forComponent.getClientId(facesContext);
1003
1004 }
1005
1006 public static List convertIdsToClientIds(String actionFor, FacesContext facesContext, UIComponent component)
1007 {
1008 List li = new ArrayList();
1009
1010 String[] ids = actionFor.split(",");
1011
1012 for (int i = 0; i < ids.length; i++)
1013 {
1014 String trimedId = ids[i].trim();
1015 if (trimedId.equals("none"))
1016 li.add(trimedId);
1017 else
1018 li.add(RendererUtils.getClientId(facesContext, component, trimedId));
1019 }
1020 return li;
1021 }
1022
1023 public static List convertPhasesToPhasesIds(String actionForPhase)
1024 {
1025 List li = new ArrayList();
1026
1027 if (actionForPhase == null)
1028 {
1029 return li;
1030 }
1031
1032 String[] ids = actionForPhase.split(",");
1033
1034 for (int i = 0; i < ids.length; i++)
1035 {
1036 if (ids[i].equals("PROCESS_VALIDATIONS"))
1037 {
1038 li.add(PhaseId.PROCESS_VALIDATIONS);
1039 }
1040 else if (ids[i].equals("UPDATE_MODEL_VALUES"))
1041 {
1042 li.add(PhaseId.UPDATE_MODEL_VALUES);
1043 }
1044 }
1045 return li;
1046 }
1047
1048 /***
1049 * Helper method which loads a resource file (such as css) by a given context path and a file name.
1050 * Useful to provide css files (or js files) inline.
1051 *
1052 * @param ctx <code>FacesContext</code> object to calculate the context path of the web application.
1053 * @param file name of the resource file (e.g. <code>foo.css</code>).
1054 * @return the content of the resource file, or <code>null</code> if no such file is available.
1055 */
1056 public static String loadResourceFile(FacesContext ctx, String file)
1057 {
1058
1059 ByteArrayOutputStream content = new ByteArrayOutputStream(10240);
1060
1061 InputStream in = null;
1062 try {
1063 in = ctx.getExternalContext().getResourceAsStream(file);
1064 if (in == null)
1065 {
1066 return null;
1067 }
1068
1069 byte[] fileBuffer = new byte[10240];
1070 int read;
1071 while ((read = in.read(fileBuffer)) > -1)
1072 {
1073 content.write(fileBuffer, 0, read);
1074 }
1075 }
1076 catch (FileNotFoundException e) {
1077 if (log.isWarnEnabled())
1078 log.warn("no such file " + file, e);
1079 content = null;
1080 }
1081 catch (IOException e) {
1082 if (log.isWarnEnabled())
1083 log.warn("problems during processing resource " + file, e);
1084 content = null;
1085 }
1086 finally
1087 {
1088 try
1089 {
1090 content.close();
1091 }
1092 catch (IOException e)
1093 {
1094 log.warn(e.getLocalizedMessage(), e);
1095 }
1096 if (in != null)
1097 {
1098 try
1099 {
1100 in.close();
1101 }
1102 catch (IOException e)
1103 {
1104 log.warn(e.getLocalizedMessage(), e);
1105 }
1106 }
1107 }
1108
1109 return content.toString();
1110 }
1111
1112 /***
1113 * check for partial validation or model update attributes being set
1114 * and initialize the request-map accordingly.
1115 * SubForms will work with this information.
1116 */
1117 public static void initPartialValidationAndModelUpdate(UIComponent component, FacesContext facesContext)
1118 {
1119 String actionFor = (String) component.getAttributes().get("actionFor");
1120
1121 if (actionFor != null)
1122 {
1123 List li = convertIdsToClientIds(actionFor, facesContext, component);
1124
1125 facesContext.getExternalContext().getRequestMap().put(ACTION_FOR_LIST, li);
1126
1127 String actionForPhase = (String) component.getAttributes().get("actionForPhase");
1128
1129 if (actionForPhase != null)
1130 {
1131 List phaseList = convertPhasesToPhasesIds(actionForPhase);
1132
1133 facesContext.getExternalContext().getRequestMap().put(ACTION_FOR_PHASE_LIST, phaseList);
1134 }
1135 }
1136 }
1137
1138 public static boolean isAdfOrTrinidadForm(UIComponent component) {
1139 if (component == null)
1140 return false;
1141 return ADF_FORM_COMPONENT_FAMILY.equals(component.getFamily()) ||
1142 TRINIDAD_FORM_COMPONENT_FAMILY.equals(component.getFamily());
1143 }
1144
1145
1146 /***
1147 * Gets the ResponseStateManager for the renderKit Id provided
1148 */
1149 public static ResponseStateManager getResponseStateManager(FacesContext facesContext, String renderKitId)
1150 throws FacesException
1151 {
1152 RenderKit renderKit = facesContext.getRenderKit();
1153
1154 if (renderKit == null)
1155 {
1156
1157 Map requestMap = facesContext.getExternalContext().getRequestMap();
1158 RenderKitFactory factory = (RenderKitFactory) requestMap.get(RENDER_KIT_IMPL);
1159
1160 if (factory != null)
1161 {
1162 renderKit = factory.getRenderKit(facesContext, renderKitId);
1163 }
1164 else
1165 {
1166 factory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
1167
1168 if (factory == null)
1169 {
1170 throw new IllegalStateException("Factory is null");
1171 }
1172
1173 requestMap.put(RENDER_KIT_IMPL, factory);
1174
1175 renderKit = factory.getRenderKit(facesContext, renderKitId);
1176 }
1177 }
1178
1179 if (renderKit == null)
1180 {
1181 throw new IllegalArgumentException("Could not find a RenderKit for \"" + renderKitId + "\"");
1182 }
1183
1184 return renderKit.getResponseStateManager();
1185 }
1186
1187 /***
1188 * Special converter for handling submitted values which don't need to be converted.
1189 *
1190 * @author mathias (latest modification by $Author: matzew $)
1191 * @version $Revision: 807542 $ $Date: 2009-08-25 05:22:20 -0500 (Tue, 25 Aug 2009) $
1192 */
1193 private static class PassThroughAsStringConverter implements Converter
1194 {
1195 private final Converter converter;
1196
1197 public PassThroughAsStringConverter(Converter converter)
1198 {
1199 this.converter = converter;
1200 }
1201
1202 public Object getAsObject(FacesContext context, UIComponent component,
1203 String value) throws ConverterException
1204 {
1205 return converter.getAsObject(context, component, value);
1206 }
1207
1208 public String getAsString(FacesContext context, UIComponent component,
1209 Object value) throws ConverterException
1210 {
1211 return (String)value;
1212 }
1213
1214 }
1215 }