1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package javax.faces.component;
20
21 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
22 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFListener;
23 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
24 import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFWebConfigParam;
25
26 import javax.el.ValueExpression;
27 import javax.faces.application.FacesMessage;
28 import javax.faces.application.ProjectStage;
29 import javax.faces.context.ExternalContext;
30 import javax.faces.context.FacesContext;
31 import javax.faces.convert.Converter;
32 import javax.faces.convert.ConverterException;
33 import javax.faces.el.EvaluationException;
34 import javax.faces.el.MethodBinding;
35 import javax.faces.event.AbortProcessingException;
36 import javax.faces.event.ExceptionQueuedEvent;
37 import javax.faces.event.ExceptionQueuedEventContext;
38 import javax.faces.event.FacesEvent;
39 import javax.faces.event.PhaseId;
40 import javax.faces.event.PostValidateEvent;
41 import javax.faces.event.PreValidateEvent;
42 import javax.faces.event.ValueChangeEvent;
43 import javax.faces.event.ValueChangeListener;
44 import javax.faces.render.Renderer;
45 import javax.faces.validator.Validator;
46 import javax.faces.webapp.FacesServlet;
47 import java.util.ArrayList;
48 import java.util.Arrays;
49 import java.util.Collection;
50 import java.util.HashMap;
51 import java.util.LinkedList;
52 import java.util.List;
53 import java.util.Map;
54
55
56
57
58
59
60
61
62 @JSFComponent(defaultRendererType = "javax.faces.Text")
63 public class UIInput extends UIOutput implements EditableValueHolder
64 {
65 public static final String COMPONENT_TYPE = "javax.faces.Input";
66 public static final String COMPONENT_FAMILY = "javax.faces.Input";
67
68 public static final String CONVERSION_MESSAGE_ID = "javax.faces.component.UIInput.CONVERSION";
69 public static final String REQUIRED_MESSAGE_ID = "javax.faces.component.UIInput.REQUIRED";
70 public static final String UPDATE_MESSAGE_ID = "javax.faces.component.UIInput.UPDATE";
71
72
73
74
75
76 @JSFWebConfigParam(defaultValue="auto", expectedValues="auto, true, false", since="2.0", group="validation")
77 public static final String VALIDATE_EMPTY_FIELDS_PARAM_NAME = "javax.faces.VALIDATE_EMPTY_FIELDS";
78
79
80
81
82
83
84 @JSFWebConfigParam(defaultValue="false", expectedValues="true, false", since="2.0", group="validation")
85 private static final String EMPTY_VALUES_AS_NULL_PARAM_NAME
86 = "javax.faces.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL";
87
88
89 private static final String MYFACES_EMPTY_VALUES_AS_NULL_PARAM_NAME =
90 "org.apache.myfaces.UIInput.INTERPRET_EMPTY_STRING_SUBMITTED_VALUES_AS_NULL";
91
92
93
94
95
96
97 private static final String DEBUG_INFO_KEY = "org.apache.myfaces.debug.DEBUG_INFO";
98
99 private static final Validator[] EMPTY_VALIDATOR_ARRAY = new Validator[0];
100
101 private _DeltaList<Validator> _validatorList;
102
103
104
105
106 public UIInput()
107 {
108 setRendererType("javax.faces.Text");
109 }
110
111 @Override
112 public String getFamily()
113 {
114 return COMPONENT_FAMILY;
115 }
116
117
118
119
120
121
122
123 @Override
124 public void setValue(Object value)
125 {
126 FacesContext facesContext = getFacesContext();
127 if (facesContext != null && facesContext.isProjectStage(ProjectStage.Development))
128 {
129
130 _createFieldDebugInfo(facesContext, "localValue",
131 getLocalValue(), value, 1);
132 }
133 setLocalValueSet(true);
134 super.setValue(value);
135 }
136
137
138
139
140
141
142
143
144
145 public Object getValue()
146 {
147 if (isLocalValueSet())
148 {
149 return super.getLocalValue();
150 }
151 return super.getValue();
152 }
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167 @Override
168 public void processDecodes(FacesContext context)
169 {
170 if (context == null)
171 {
172 throw new NullPointerException("context");
173 }
174 try
175 {
176 setCachedFacesContext(context);
177 pushComponentToEL(context, this);
178 if (!isRendered())
179 {
180 return;
181 }
182 }
183 finally
184 {
185 setCachedFacesContext(null);
186 popComponentFromEL(context);
187 }
188 super.processDecodes(context);
189 try
190 {
191 setCachedFacesContext(context);
192 pushComponentToEL(context, this);
193 if (isImmediate())
194 {
195
196 context.getApplication().publishEvent(context, PreValidateEvent.class, getClass(), this);
197 try
198 {
199 validate(context);
200 }
201 catch (RuntimeException e)
202 {
203 context.renderResponse();
204 throw e;
205 }
206 finally
207 {
208 context.getApplication().publishEvent(context, PostValidateEvent.class, getClass(), this);
209 }
210 if (!isValid())
211 {
212 context.renderResponse();
213 }
214 }
215 }
216 finally
217 {
218 setCachedFacesContext(null);
219 popComponentFromEL(context);
220 }
221 }
222
223 @Override
224 public void processValidators(FacesContext context)
225 {
226 if (context == null)
227 {
228 throw new NullPointerException("context");
229 }
230 try
231 {
232 setCachedFacesContext(context);
233 pushComponentToEL(context, this);
234 if (!isRendered())
235 {
236 return;
237 }
238 }
239 finally
240 {
241 setCachedFacesContext(null);
242 popComponentFromEL(context);
243 }
244
245
246
247
248
249 int facetCount = getFacetCount();
250 if (facetCount > 0)
251 {
252 for (UIComponent facet : getFacets().values())
253 {
254 facet.processValidators(context);
255 }
256 }
257
258 for (int i = 0, childCount = getChildCount(); i < childCount; i++)
259 {
260 UIComponent child = getChildren().get(i);
261 child.processValidators(context);
262 }
263
264 try
265 {
266 setCachedFacesContext(context);
267 pushComponentToEL(context, this);
268 if (!isImmediate())
269 {
270
271 context.getApplication().publishEvent(context, PreValidateEvent.class, getClass(), this);
272 try
273 {
274 validate(context);
275 }
276 catch (RuntimeException e)
277 {
278 context.renderResponse();
279 throw e;
280 }
281 finally
282 {
283 context.getApplication().publishEvent(context, PostValidateEvent.class, getClass(), this);
284 }
285 if (!isValid())
286 {
287 context.validationFailed();
288 context.renderResponse();
289 }
290 }
291 }
292 finally
293 {
294 setCachedFacesContext(null);
295 popComponentFromEL(context);
296 }
297 }
298
299 @Override
300 public void processUpdates(FacesContext context)
301 {
302 if (context == null)
303 {
304 throw new NullPointerException("context");
305 }
306 try
307 {
308 setCachedFacesContext(context);
309 pushComponentToEL(context, this);
310 if (!isRendered())
311 {
312 return;
313 }
314 }
315 finally
316 {
317 setCachedFacesContext(null);
318 popComponentFromEL(context);
319 }
320 super.processUpdates(context);
321
322 try
323 {
324 setCachedFacesContext(context);
325 pushComponentToEL(context, this);
326 try
327 {
328 updateModel(context);
329 }
330 catch (RuntimeException e)
331 {
332 context.renderResponse();
333 throw e;
334 }
335 if (!isValid())
336 {
337 context.renderResponse();
338 }
339 }
340 finally
341 {
342 setCachedFacesContext(null);
343 popComponentFromEL(context);
344 }
345 }
346
347 @Override
348 public void decode(FacesContext context)
349 {
350
351 setValid(true);
352 super.decode(context);
353 }
354
355 @Override
356 public void broadcast(FacesEvent event) throws AbortProcessingException
357 {
358
359 super.broadcast(event);
360
361
362 if (event instanceof ValueChangeEvent)
363 {
364
365 MethodBinding valueChangeListenerBinding = getValueChangeListener();
366 if (valueChangeListenerBinding != null)
367 {
368 try
369 {
370 valueChangeListenerBinding.invoke(getFacesContext(), new Object[] { event });
371 }
372 catch (EvaluationException e)
373 {
374 Throwable cause = e.getCause();
375 if (cause != null && cause instanceof AbortProcessingException)
376 {
377 throw (AbortProcessingException) cause;
378 }
379 else
380 {
381 throw e;
382 }
383 }
384 }
385 }
386 }
387
388 public void updateModel(FacesContext context)
389 {
390 if (!isValid())
391 {
392 return;
393 }
394 if (!isLocalValueSet())
395 {
396 return;
397 }
398 ValueExpression expression = getValueExpression("value");
399 if (expression == null)
400 {
401 return;
402 }
403
404 try
405 {
406 expression.setValue(context.getELContext(), getLocalValue());
407 setValue(null);
408 setLocalValueSet(false);
409 }
410 catch (Exception e)
411 {
412
413
414
415
416 FacesMessage facesMessage = _MessageUtils.getMessage(context,
417 context.getViewRoot().getLocale(), FacesMessage.SEVERITY_ERROR, UPDATE_MESSAGE_ID,
418 new Object[] { _MessageUtils.getLabel(context, this) });
419
420
421
422
423
424 UpdateModelException updateModelException = new UpdateModelException(facesMessage, e);
425 ExceptionQueuedEventContext exceptionQueuedContext
426 = new ExceptionQueuedEventContext(context, updateModelException, this, PhaseId.UPDATE_MODEL_VALUES);
427
428
429
430 context.getApplication().publishEvent(context, ExceptionQueuedEvent.class, exceptionQueuedContext);
431
432
433 setValid(false);
434 }
435 }
436
437 protected void validateValue(FacesContext context, Object convertedValue)
438 {
439 if (!isValid())
440 {
441 return;
442 }
443
444
445 boolean isEmpty = isEmpty(convertedValue);
446
447 if (isRequired() && isEmpty)
448 {
449 if (getRequiredMessage() != null)
450 {
451 String requiredMessage = getRequiredMessage();
452 context.addMessage(this.getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,
453 requiredMessage, requiredMessage));
454 }
455 else
456 {
457 _MessageUtils.addErrorMessage(context, this, REQUIRED_MESSAGE_ID,
458 new Object[] { _MessageUtils.getLabel(context, this) });
459 }
460 setValid(false);
461 return;
462 }
463
464 if (!isEmpty || shouldValidateEmptyFields(context))
465 {
466 _ComponentUtils.callValidators(context, this, convertedValue);
467 }
468 }
469
470
471
472
473
474
475
476 private boolean shouldInterpretEmptyStringSubmittedValuesAsNull(FacesContext context)
477 {
478 ExternalContext ec = context.getExternalContext();
479 Boolean interpretEmptyStringAsNull
480 = (Boolean)ec.getApplicationMap().get(MYFACES_EMPTY_VALUES_AS_NULL_PARAM_NAME);
481
482
483 if (interpretEmptyStringAsNull == null)
484 {
485
486 String param = ec.getInitParameter(EMPTY_VALUES_AS_NULL_PARAM_NAME);
487
488
489 interpretEmptyStringAsNull = "true".equalsIgnoreCase(param);
490
491
492 ec.getApplicationMap().put(MYFACES_EMPTY_VALUES_AS_NULL_PARAM_NAME, interpretEmptyStringAsNull);
493 }
494
495 return interpretEmptyStringAsNull;
496 }
497
498
499
500
501 private boolean isEmptyString(Object value)
502 {
503 return ((value instanceof String) && (((String) value).length() == 0));
504 }
505
506
507 private boolean shouldValidateEmptyFields(FacesContext context)
508 {
509 ExternalContext ec = context.getExternalContext();
510 Boolean validateEmptyFields = (Boolean) ec.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
511
512 if (validateEmptyFields == null)
513 {
514 String param = ec.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
515
516
517 if (param == null)
518 {
519 param = "auto";
520 }
521 else
522 {
523
524 param = param.toLowerCase();
525 }
526
527 if (param.equals("auto") && _ExternalSpecifications.isBeanValidationAvailable())
528 {
529 validateEmptyFields = true;
530 }
531 else if (param.equals("true"))
532 {
533 validateEmptyFields = true;
534 }
535 else
536 {
537 validateEmptyFields = false;
538 }
539
540
541 ec.getApplicationMap().put(VALIDATE_EMPTY_FIELDS_PARAM_NAME, validateEmptyFields);
542 }
543
544 return validateEmptyFields;
545 }
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568 public void validate(FacesContext context)
569 {
570 if (context == null)
571 {
572 throw new NullPointerException("context");
573 }
574
575 Object submittedValue = getSubmittedValue();
576 if (submittedValue == null)
577 {
578 return;
579 }
580
581
582 if (shouldInterpretEmptyStringSubmittedValuesAsNull(context) && isEmptyString(submittedValue))
583 {
584
585
586 setSubmittedValue(null);
587 submittedValue = null;
588 }
589
590
591 Object convertedValue;
592 try
593 {
594 convertedValue = getConvertedValue(context, submittedValue);
595 }
596 catch (ConverterException e)
597 {
598 String converterMessage = getConverterMessage();
599 if (converterMessage != null)
600 {
601 context.addMessage(getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,
602 converterMessage, converterMessage));
603 }
604 else
605 {
606 FacesMessage facesMessage = e.getFacesMessage();
607 if (facesMessage != null)
608 {
609 context.addMessage(getClientId(context), facesMessage);
610 }
611 else
612 {
613 _MessageUtils.addErrorMessage(context, this, CONVERSION_MESSAGE_ID,
614 new Object[] { _MessageUtils.getLabel(context, this) });
615 }
616 }
617 setValid(false);
618 return;
619 }
620
621 validateValue(context, convertedValue);
622
623 if (!isValid())
624 {
625 return;
626 }
627
628 Object previousValue = getValue();
629 setValue(convertedValue);
630 setSubmittedValue(null);
631 if (compareValues(previousValue, convertedValue))
632 {
633 queueEvent(new ValueChangeEvent(this, previousValue, convertedValue));
634 }
635 }
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653 protected Object getConvertedValue(FacesContext context, Object submittedValue) throws ConverterException
654 {
655 Renderer renderer = getRenderer(context);
656 if (renderer != null)
657 {
658 return renderer.getConvertedValue(context, this, submittedValue);
659 }
660 else if (submittedValue instanceof String)
661 {
662 Converter converter = _SharedRendererUtils.findUIOutputConverter(context, this);
663 if (converter != null)
664 {
665 return converter.getAsObject(context, this, (String) submittedValue);
666 }
667 }
668 return submittedValue;
669 }
670
671 protected boolean compareValues(Object previous, Object value)
672 {
673 return previous == null ? (value != null) : (!previous.equals(value));
674 }
675
676
677
678
679 public void resetValue()
680 {
681 setSubmittedValue(null);
682 setValue(null);
683 setLocalValueSet(false);
684 setValid(true);
685 }
686
687
688
689
690
691
692
693
694
695 @JSFProperty
696 public boolean isImmediate()
697 {
698 return (Boolean) getStateHelper().eval(PropertyKeys.immediate, Boolean.FALSE);
699 }
700
701 public void setImmediate(boolean immediate)
702 {
703 getStateHelper().put(PropertyKeys.immediate, immediate );
704 }
705
706
707
708
709
710
711
712
713
714
715
716 @JSFProperty(defaultValue = "false")
717 public boolean isRequired()
718 {
719 return (Boolean) getStateHelper().eval(PropertyKeys.required, Boolean.FALSE);
720 }
721
722 public void setRequired(boolean required)
723 {
724 getStateHelper().put(PropertyKeys.required, required );
725 }
726
727
728
729
730
731
732
733 @JSFProperty
734 public String getConverterMessage()
735 {
736 return (String) getStateHelper().eval(PropertyKeys.converterMessage);
737 }
738
739 public void setConverterMessage(String converterMessage)
740 {
741 getStateHelper().put(PropertyKeys.converterMessage, converterMessage );
742 }
743
744
745
746
747
748 @JSFProperty
749 public String getRequiredMessage()
750 {
751 return (String) getStateHelper().eval(PropertyKeys.requiredMessage);
752 }
753
754 public void setRequiredMessage(String requiredMessage)
755 {
756 getStateHelper().put(PropertyKeys.requiredMessage, requiredMessage );
757 }
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772 @SuppressWarnings("dep-ann")
773 @JSFProperty(stateHolder=true, returnSignature = "void",
774 methodSignature = "javax.faces.context.FacesContext,javax.faces.component.UIComponent,java.lang.Object")
775 public MethodBinding getValidator()
776 {
777 return (MethodBinding) getStateHelper().eval(PropertyKeys.validator);
778 }
779
780
781
782
783
784 public void setValidator(MethodBinding validator)
785 {
786 getStateHelper().put(PropertyKeys.validator, validator);
787 }
788
789
790 public void addValidator(Validator validator)
791 {
792 if (validator == null)
793 {
794 throw new NullPointerException("validator");
795 }
796
797 if (_validatorList == null)
798 {
799
800 _validatorList = new _DeltaList<Validator>(new ArrayList<Validator>(3));
801 }
802
803 _validatorList.add(validator);
804
805
806
807 }
808
809
810 public void removeValidator(Validator validator)
811 {
812 if (validator == null || _validatorList == null)
813 {
814 return;
815 }
816
817 _validatorList.remove(validator);
818 }
819
820
821 public Validator[] getValidators()
822 {
823 return _validatorList == null ? EMPTY_VALIDATOR_ARRAY
824 : _validatorList.toArray(new Validator[_validatorList.size()]);
825 }
826
827
828
829
830 @JSFProperty
831 public String getValidatorMessage()
832 {
833 return (String) getStateHelper().eval(PropertyKeys.validatorMessage);
834 }
835
836 public void setValidatorMessage(String validatorMessage)
837 {
838 getStateHelper().put(PropertyKeys.validatorMessage, validatorMessage );
839 }
840
841
842
843
844
845
846
847
848
849
850 @JSFProperty(stateHolder=true, returnSignature = "void",
851 methodSignature = "javax.faces.event.ValueChangeEvent", clientEvent="valueChange")
852 public MethodBinding getValueChangeListener()
853 {
854 return (MethodBinding) getStateHelper().eval(PropertyKeys.valueChangeListener);
855 }
856
857
858
859
860
861
862 public void setValueChangeListener(MethodBinding valueChangeListener)
863 {
864 getStateHelper().put(PropertyKeys.valueChangeListener, valueChangeListener);
865 }
866
867
868
869
870
871 @JSFProperty(defaultValue = "true", tagExcluded = true)
872 public boolean isValid()
873 {
874 Object value = getStateHelper().get(PropertyKeys.valid);
875 if (value != null)
876 {
877 return (Boolean) value;
878 }
879 return true;
880 }
881
882 public void setValid(boolean valid)
883 {
884
885
886
887
888 if (getStateHelper().get(PropertyKeys.valid) != null || !valid)
889 {
890 getStateHelper().put(PropertyKeys.valid, valid );
891 }
892 }
893
894
895
896
897
898
899 @JSFProperty(defaultValue = "false", tagExcluded = true)
900 public boolean isLocalValueSet()
901 {
902 Object value = getStateHelper().get(PropertyKeys.localValueSet);
903 if (value != null)
904 {
905 return (Boolean) value;
906 }
907 return false;
908 }
909
910 public void setLocalValueSet(boolean localValueSet)
911 {
912
913
914
915
916 if (getStateHelper().get(PropertyKeys.localValueSet) != null || localValueSet)
917 {
918 getStateHelper().put(PropertyKeys.localValueSet, localValueSet );
919 }
920 }
921
922
923
924
925
926
927
928 @JSFProperty(tagExcluded = true)
929 public Object getSubmittedValue()
930 {
931 return getStateHelper().get(PropertyKeys.submittedValue);
932 }
933
934 public void setSubmittedValue(Object submittedValue)
935 {
936 FacesContext facesContext = getFacesContext();
937 if (facesContext != null && facesContext.isProjectStage(ProjectStage.Development))
938 {
939
940 _createFieldDebugInfo(facesContext, "submittedValue",
941 getSubmittedValue(), submittedValue, 1);
942 }
943 getStateHelper().put(PropertyKeys.submittedValue, submittedValue );
944 }
945
946 public void addValueChangeListener(ValueChangeListener listener)
947 {
948 addFacesListener(listener);
949 }
950
951 public void removeValueChangeListener(ValueChangeListener listener)
952 {
953 removeFacesListener(listener);
954 }
955
956
957
958
959
960 @JSFListener(event="javax.faces.event.ValueChangeEvent")
961 public ValueChangeListener[] getValueChangeListeners()
962 {
963 return (ValueChangeListener[]) getFacesListeners(ValueChangeListener.class);
964 }
965
966 enum PropertyKeys
967 {
968 immediate
969 , required
970 , converterMessage
971 , requiredMessage
972 , validator
973 , validatorListSet
974 , validatorMessage
975 , valueChangeListener
976 , valid
977 , localValueSet
978 , submittedValue
979 }
980
981 private static final Object[] INITIAL_STATE_PROPERTIES = new
982 Object[]{
983 UIOutput.PropertyKeys.value,
984 null,
985 UIInput.PropertyKeys.localValueSet,
986 false,
987 UIInput.PropertyKeys.submittedValue,
988 null,
989 UIInput.PropertyKeys.valid,
990 true
991 };
992
993 public void markInitialState()
994 {
995 StateHelper helper = getStateHelper(false);
996 if (helper != null && helper instanceof _DeltaStateHelper)
997 {
998 ((_DeltaStateHelper)helper).markPropertyInInitialState(INITIAL_STATE_PROPERTIES);
999 }
1000 super.markInitialState();
1001 if (_validatorList != null)
1002 {
1003 _validatorList.markInitialState();
1004 }
1005 }
1006
1007 public void clearInitialState()
1008 {
1009 if (initialStateMarked())
1010 {
1011 super.clearInitialState();
1012 if (_validatorList != null)
1013 {
1014 _validatorList.clearInitialState();
1015 }
1016 }
1017 }
1018
1019 @Override
1020 public Object saveState(FacesContext facesContext)
1021 {
1022 if (initialStateMarked())
1023 {
1024 Object parentSaved = super.saveState(facesContext);
1025 Object validatorListSaved = saveValidatorList(facesContext);
1026 if (parentSaved == null && validatorListSaved == null)
1027 {
1028
1029 return null;
1030 }
1031
1032 Object[] values = new Object[2];
1033 values[0] = parentSaved;
1034 values[1] = validatorListSaved;
1035 return values;
1036 }
1037 else
1038 {
1039 Object[] values = new Object[2];
1040 values[0] = super.saveState(facesContext);
1041 values[1] = saveValidatorList(facesContext);
1042 return values;
1043 }
1044 }
1045
1046 @SuppressWarnings("unchecked")
1047 @Override
1048 public void restoreState(FacesContext facesContext, Object state)
1049 {
1050 if (state == null)
1051 {
1052 return;
1053 }
1054
1055 Object[] values = (Object[])state;
1056 super.restoreState(facesContext,values[0]);
1057 if (values[1] instanceof _AttachedDeltaWrapper)
1058 {
1059
1060 if (_validatorList != null)
1061 {
1062 ((StateHolder)_validatorList).restoreState(facesContext,
1063 ((_AttachedDeltaWrapper) values[1]).getWrappedStateObject());
1064 }
1065 }
1066 else if (values[1] != null || !initialStateMarked())
1067 {
1068
1069 _validatorList = (_DeltaList<Validator>)
1070 restoreAttachedState(facesContext,values[1]);
1071 }
1072 }
1073
1074 private Object saveValidatorList(FacesContext facesContext)
1075 {
1076 PartialStateHolder holder = (PartialStateHolder) _validatorList;
1077 if (initialStateMarked() && _validatorList != null && holder.initialStateMarked())
1078 {
1079 Object attachedState = holder.saveState(facesContext);
1080 if (attachedState != null)
1081 {
1082 return new _AttachedDeltaWrapper(_validatorList.getClass(),
1083 attachedState);
1084 }
1085
1086 return null;
1087 }
1088 else
1089 {
1090 return saveAttachedState(facesContext,_validatorList);
1091 }
1092 }
1093
1094
1095
1096
1097
1098 @SuppressWarnings("unchecked")
1099 private Map<String, List<Object[]>> _getDebugInfoMap()
1100 {
1101 Map<String, Object> requestMap = getFacesContext()
1102 .getExternalContext().getRequestMap();
1103 Map<String, List<Object[]>> debugInfo = (Map<String, List<Object[]>>)
1104 requestMap.get(DEBUG_INFO_KEY + getClientId());
1105 if (debugInfo == null)
1106 {
1107
1108 debugInfo = new HashMap<String, List<Object[]>>();
1109 requestMap.put(DEBUG_INFO_KEY + getClientId(), debugInfo);
1110 }
1111 return debugInfo;
1112 }
1113
1114
1115
1116
1117
1118
1119 private List<Object[]> _getFieldDebugInfos(final String field)
1120 {
1121 Map<String, List<Object[]>> debugInfo = _getDebugInfoMap();
1122 List<Object[]> fieldDebugInfo = debugInfo.get(field);
1123 if (fieldDebugInfo == null)
1124 {
1125
1126 fieldDebugInfo = new ArrayList<Object[]>();
1127 debugInfo.put(field, fieldDebugInfo);
1128 }
1129 return fieldDebugInfo;
1130 }
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143 private void _createFieldDebugInfo(FacesContext facesContext,
1144 final String field, Object oldValue,
1145 Object newValue, final int skipStackTaceElements)
1146 {
1147 if (oldValue == null && newValue == null)
1148 {
1149
1150
1151 return;
1152 }
1153
1154 if (facesContext.getViewRoot() == null)
1155 {
1156
1157
1158
1159
1160 return;
1161 }
1162
1163 if (getParent() == null || !isInView())
1164 {
1165
1166 return;
1167 }
1168
1169
1170 if (oldValue != null && oldValue.getClass().isArray() && Object[].class.isAssignableFrom(oldValue.getClass()))
1171 {
1172 oldValue = Arrays.deepToString((Object[]) oldValue);
1173 }
1174 if (newValue != null && newValue.getClass().isArray() && Object[].class.isAssignableFrom(newValue.getClass()))
1175 {
1176 newValue = Arrays.deepToString((Object[]) newValue);
1177 }
1178
1179
1180 Throwable throwableHelper = new Throwable();
1181 StackTraceElement[] stackTraceElements = throwableHelper.getStackTrace();
1182 List<StackTraceElement> debugStackTraceElements = new LinkedList<StackTraceElement>();
1183
1184
1185 for (int i = skipStackTaceElements + 1; i < stackTraceElements.length; i++)
1186 {
1187 debugStackTraceElements.add(stackTraceElements[i]);
1188
1189 if (FacesServlet.class.getCanonicalName()
1190 .equals(stackTraceElements[i].getClassName()))
1191 {
1192
1193 break;
1194 }
1195 }
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205 Object[] debugInfo = new Object[4];
1206 debugInfo[0] = facesContext.getCurrentPhaseId();
1207 debugInfo[1] = oldValue;
1208 debugInfo[2] = newValue;
1209 debugInfo[3] = debugStackTraceElements;
1210
1211
1212 _getFieldDebugInfos(field).add(debugInfo);
1213 }
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223 public static boolean isEmpty(Object value)
1224 {
1225 if (value == null)
1226 {
1227 return true;
1228 }
1229 else if (value instanceof String)
1230 {
1231 if ( ((String)value).trim().length() <= 0 )
1232 {
1233 return true;
1234 }
1235 }
1236 else if (value instanceof Collection)
1237 {
1238 if ( ((Collection)value).isEmpty())
1239 {
1240 return true;
1241 }
1242 }
1243 else if (value.getClass().isArray())
1244 {
1245 if (java.lang.reflect.Array.getLength(value) <= 0)
1246 {
1247 return true;
1248 }
1249 }
1250 else if (value instanceof Map)
1251 {
1252 if ( ((Map)value).isEmpty())
1253 {
1254 return true;
1255 }
1256 }
1257 return false;
1258 }
1259
1260 }