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 private boolean shouldValidateEmptyFields(FacesContext context)
507 {
508 ExternalContext extCtx = context.getExternalContext();
509 String validateEmptyFields = (String) extCtx.getInitParameter(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
510 if (validateEmptyFields == null)
511 {
512 validateEmptyFields = (String) extCtx.getApplicationMap().get(VALIDATE_EMPTY_FIELDS_PARAM_NAME);
513 }
514
515
516 if (validateEmptyFields == null)
517 {
518 validateEmptyFields = "auto";
519 }
520 else
521 {
522
523 validateEmptyFields = validateEmptyFields.toLowerCase();
524 }
525
526 if (validateEmptyFields.equals("auto") && _ExternalSpecifications.isBeanValidationAvailable())
527 {
528 return true;
529 }
530 else if (validateEmptyFields.equals("true"))
531 {
532 return true;
533 }
534 return false;
535 }
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558 public void validate(FacesContext context)
559 {
560 if (context == null)
561 {
562 throw new NullPointerException("context");
563 }
564
565 Object submittedValue = getSubmittedValue();
566 if (submittedValue == null)
567 {
568 return;
569 }
570
571
572 if (shouldInterpretEmptyStringSubmittedValuesAsNull(context) && isEmptyString(submittedValue))
573 {
574
575
576 setSubmittedValue(null);
577 submittedValue = null;
578 }
579
580
581 Object convertedValue;
582 try
583 {
584 convertedValue = getConvertedValue(context, submittedValue);
585 }
586 catch (ConverterException e)
587 {
588 String converterMessage = getConverterMessage();
589 if (converterMessage != null)
590 {
591 context.addMessage(getClientId(context), new FacesMessage(FacesMessage.SEVERITY_ERROR,
592 converterMessage, converterMessage));
593 }
594 else
595 {
596 FacesMessage facesMessage = e.getFacesMessage();
597 if (facesMessage != null)
598 {
599 context.addMessage(getClientId(context), facesMessage);
600 }
601 else
602 {
603 _MessageUtils.addErrorMessage(context, this, CONVERSION_MESSAGE_ID,
604 new Object[] { _MessageUtils.getLabel(context, this) });
605 }
606 }
607 setValid(false);
608 return;
609 }
610
611 validateValue(context, convertedValue);
612
613 if (!isValid())
614 {
615 return;
616 }
617
618 Object previousValue = getValue();
619 setValue(convertedValue);
620 setSubmittedValue(null);
621 if (compareValues(previousValue, convertedValue))
622 {
623 queueEvent(new ValueChangeEvent(this, previousValue, convertedValue));
624 }
625 }
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643 protected Object getConvertedValue(FacesContext context, Object submittedValue) throws ConverterException
644 {
645 Renderer renderer = getRenderer(context);
646 if (renderer != null)
647 {
648 return renderer.getConvertedValue(context, this, submittedValue);
649 }
650 else if (submittedValue instanceof String)
651 {
652 Converter converter = _SharedRendererUtils.findUIOutputConverter(context, this);
653 if (converter != null)
654 {
655 return converter.getAsObject(context, this, (String) submittedValue);
656 }
657 }
658 return submittedValue;
659 }
660
661 protected boolean compareValues(Object previous, Object value)
662 {
663 return previous == null ? (value != null) : (!previous.equals(value));
664 }
665
666
667
668
669 public void resetValue()
670 {
671 setSubmittedValue(null);
672 setValue(null);
673 setLocalValueSet(false);
674 setValid(true);
675 }
676
677
678
679
680
681
682
683
684
685 @JSFProperty
686 public boolean isImmediate()
687 {
688 return (Boolean) getStateHelper().eval(PropertyKeys.immediate, Boolean.FALSE);
689 }
690
691 public void setImmediate(boolean immediate)
692 {
693 getStateHelper().put(PropertyKeys.immediate, immediate );
694 }
695
696
697
698
699
700
701
702
703
704
705
706 @JSFProperty(defaultValue = "false")
707 public boolean isRequired()
708 {
709 return (Boolean) getStateHelper().eval(PropertyKeys.required, Boolean.FALSE);
710 }
711
712 public void setRequired(boolean required)
713 {
714 getStateHelper().put(PropertyKeys.required, required );
715 }
716
717
718
719
720
721
722
723 @JSFProperty
724 public String getConverterMessage()
725 {
726 return (String) getStateHelper().eval(PropertyKeys.converterMessage);
727 }
728
729 public void setConverterMessage(String converterMessage)
730 {
731 getStateHelper().put(PropertyKeys.converterMessage, converterMessage );
732 }
733
734
735
736
737
738 @JSFProperty
739 public String getRequiredMessage()
740 {
741 return (String) getStateHelper().eval(PropertyKeys.requiredMessage);
742 }
743
744 public void setRequiredMessage(String requiredMessage)
745 {
746 getStateHelper().put(PropertyKeys.requiredMessage, requiredMessage );
747 }
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762 @SuppressWarnings("dep-ann")
763 @JSFProperty(stateHolder=true, returnSignature = "void",
764 methodSignature = "javax.faces.context.FacesContext,javax.faces.component.UIComponent,java.lang.Object")
765 public MethodBinding getValidator()
766 {
767 return (MethodBinding) getStateHelper().eval(PropertyKeys.validator);
768 }
769
770
771
772
773
774 public void setValidator(MethodBinding validator)
775 {
776 getStateHelper().put(PropertyKeys.validator, validator);
777 }
778
779
780 public void addValidator(Validator validator)
781 {
782 if (validator == null)
783 {
784 throw new NullPointerException("validator");
785 }
786
787 if (_validatorList == null)
788 {
789
790 _validatorList = new _DeltaList<Validator>(new ArrayList<Validator>(3));
791 }
792
793 _validatorList.add(validator);
794
795
796
797 }
798
799
800 public void removeValidator(Validator validator)
801 {
802 if (validator == null || _validatorList == null)
803 {
804 return;
805 }
806
807 _validatorList.remove(validator);
808 }
809
810
811 public Validator[] getValidators()
812 {
813 return _validatorList == null ? EMPTY_VALIDATOR_ARRAY
814 : _validatorList.toArray(new Validator[_validatorList.size()]);
815 }
816
817
818
819
820 @JSFProperty
821 public String getValidatorMessage()
822 {
823 return (String) getStateHelper().eval(PropertyKeys.validatorMessage);
824 }
825
826 public void setValidatorMessage(String validatorMessage)
827 {
828 getStateHelper().put(PropertyKeys.validatorMessage, validatorMessage );
829 }
830
831
832
833
834
835
836
837
838
839
840 @JSFProperty(stateHolder=true, returnSignature = "void",
841 methodSignature = "javax.faces.event.ValueChangeEvent", clientEvent="valueChange")
842 public MethodBinding getValueChangeListener()
843 {
844 return (MethodBinding) getStateHelper().eval(PropertyKeys.valueChangeListener);
845 }
846
847
848
849
850
851
852 public void setValueChangeListener(MethodBinding valueChangeListener)
853 {
854 getStateHelper().put(PropertyKeys.valueChangeListener, valueChangeListener);
855 }
856
857
858
859
860
861 @JSFProperty(defaultValue = "true", tagExcluded = true)
862 public boolean isValid()
863 {
864 Object value = getStateHelper().get(PropertyKeys.valid);
865 if (value != null)
866 {
867 return (Boolean) value;
868 }
869 return true;
870 }
871
872 public void setValid(boolean valid)
873 {
874
875
876
877
878 if (getStateHelper().get(PropertyKeys.valid) != null || !valid)
879 {
880 getStateHelper().put(PropertyKeys.valid, valid );
881 }
882 }
883
884
885
886
887
888
889 @JSFProperty(defaultValue = "false", tagExcluded = true)
890 public boolean isLocalValueSet()
891 {
892 Object value = getStateHelper().get(PropertyKeys.localValueSet);
893 if (value != null)
894 {
895 return (Boolean) value;
896 }
897 return false;
898 }
899
900 public void setLocalValueSet(boolean localValueSet)
901 {
902
903
904
905
906 if (getStateHelper().get(PropertyKeys.localValueSet) != null || localValueSet)
907 {
908 getStateHelper().put(PropertyKeys.localValueSet, localValueSet );
909 }
910 }
911
912
913
914
915
916
917
918 @JSFProperty(tagExcluded = true)
919 public Object getSubmittedValue()
920 {
921 return getStateHelper().get(PropertyKeys.submittedValue);
922 }
923
924 public void setSubmittedValue(Object submittedValue)
925 {
926 FacesContext facesContext = getFacesContext();
927 if (facesContext != null && facesContext.isProjectStage(ProjectStage.Development))
928 {
929
930 _createFieldDebugInfo(facesContext, "submittedValue",
931 getSubmittedValue(), submittedValue, 1);
932 }
933 getStateHelper().put(PropertyKeys.submittedValue, submittedValue );
934 }
935
936 public void addValueChangeListener(ValueChangeListener listener)
937 {
938 addFacesListener(listener);
939 }
940
941 public void removeValueChangeListener(ValueChangeListener listener)
942 {
943 removeFacesListener(listener);
944 }
945
946
947
948
949
950 @JSFListener(event="javax.faces.event.ValueChangeEvent")
951 public ValueChangeListener[] getValueChangeListeners()
952 {
953 return (ValueChangeListener[]) getFacesListeners(ValueChangeListener.class);
954 }
955
956 enum PropertyKeys
957 {
958 immediate
959 , required
960 , converterMessage
961 , requiredMessage
962 , validator
963 , validatorListSet
964 , validatorMessage
965 , valueChangeListener
966 , valid
967 , localValueSet
968 , submittedValue
969 }
970
971 private static final Object[] INITIAL_STATE_PROPERTIES = new
972 Object[]{
973 UIOutput.PropertyKeys.value,
974 null,
975 UIInput.PropertyKeys.localValueSet,
976 false,
977 UIInput.PropertyKeys.submittedValue,
978 null,
979 UIInput.PropertyKeys.valid,
980 true
981 };
982
983 public void markInitialState()
984 {
985 StateHelper helper = getStateHelper(false);
986 if (helper != null && helper instanceof _DeltaStateHelper)
987 {
988 ((_DeltaStateHelper)helper).markPropertyInInitialState(INITIAL_STATE_PROPERTIES);
989 }
990 super.markInitialState();
991 if (_validatorList != null)
992 {
993 _validatorList.markInitialState();
994 }
995 }
996
997 public void clearInitialState()
998 {
999 if (initialStateMarked())
1000 {
1001 super.clearInitialState();
1002 if (_validatorList != null)
1003 {
1004 _validatorList.clearInitialState();
1005 }
1006 }
1007 }
1008
1009 @Override
1010 public Object saveState(FacesContext facesContext)
1011 {
1012 if (initialStateMarked())
1013 {
1014 Object parentSaved = super.saveState(facesContext);
1015 Object validatorListSaved = saveValidatorList(facesContext);
1016 if (parentSaved == null && validatorListSaved == null)
1017 {
1018
1019 return null;
1020 }
1021
1022 Object[] values = new Object[2];
1023 values[0] = parentSaved;
1024 values[1] = validatorListSaved;
1025 return values;
1026 }
1027 else
1028 {
1029 Object[] values = new Object[2];
1030 values[0] = super.saveState(facesContext);
1031 values[1] = saveValidatorList(facesContext);
1032 return values;
1033 }
1034 }
1035
1036 @SuppressWarnings("unchecked")
1037 @Override
1038 public void restoreState(FacesContext facesContext, Object state)
1039 {
1040 if (state == null)
1041 {
1042 return;
1043 }
1044
1045 Object[] values = (Object[])state;
1046 super.restoreState(facesContext,values[0]);
1047 if (values[1] instanceof _AttachedDeltaWrapper)
1048 {
1049
1050 if (_validatorList != null)
1051 {
1052 ((StateHolder)_validatorList).restoreState(facesContext,
1053 ((_AttachedDeltaWrapper) values[1]).getWrappedStateObject());
1054 }
1055 }
1056 else if (values[1] != null || !initialStateMarked())
1057 {
1058
1059 _validatorList = (_DeltaList<Validator>)
1060 restoreAttachedState(facesContext,values[1]);
1061 }
1062 }
1063
1064 private Object saveValidatorList(FacesContext facesContext)
1065 {
1066 PartialStateHolder holder = (PartialStateHolder) _validatorList;
1067 if (initialStateMarked() && _validatorList != null && holder.initialStateMarked())
1068 {
1069 Object attachedState = holder.saveState(facesContext);
1070 if (attachedState != null)
1071 {
1072 return new _AttachedDeltaWrapper(_validatorList.getClass(),
1073 attachedState);
1074 }
1075
1076 return null;
1077 }
1078 else
1079 {
1080 return saveAttachedState(facesContext,_validatorList);
1081 }
1082 }
1083
1084
1085
1086
1087
1088 @SuppressWarnings("unchecked")
1089 private Map<String, List<Object[]>> _getDebugInfoMap()
1090 {
1091 Map<String, Object> requestMap = getFacesContext()
1092 .getExternalContext().getRequestMap();
1093 Map<String, List<Object[]>> debugInfo = (Map<String, List<Object[]>>)
1094 requestMap.get(DEBUG_INFO_KEY + getClientId());
1095 if (debugInfo == null)
1096 {
1097
1098 debugInfo = new HashMap<String, List<Object[]>>();
1099 requestMap.put(DEBUG_INFO_KEY + getClientId(), debugInfo);
1100 }
1101 return debugInfo;
1102 }
1103
1104
1105
1106
1107
1108
1109 private List<Object[]> _getFieldDebugInfos(final String field)
1110 {
1111 Map<String, List<Object[]>> debugInfo = _getDebugInfoMap();
1112 List<Object[]> fieldDebugInfo = debugInfo.get(field);
1113 if (fieldDebugInfo == null)
1114 {
1115
1116 fieldDebugInfo = new ArrayList<Object[]>();
1117 debugInfo.put(field, fieldDebugInfo);
1118 }
1119 return fieldDebugInfo;
1120 }
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133 private void _createFieldDebugInfo(FacesContext facesContext,
1134 final String field, Object oldValue,
1135 Object newValue, final int skipStackTaceElements)
1136 {
1137 if (oldValue == null && newValue == null)
1138 {
1139
1140
1141 return;
1142 }
1143
1144 if (facesContext.getViewRoot() == null)
1145 {
1146
1147
1148
1149
1150 return;
1151 }
1152
1153 if (getParent() == null || !isInView())
1154 {
1155
1156 return;
1157 }
1158
1159
1160 if (oldValue != null && oldValue.getClass().isArray() && Object[].class.isAssignableFrom(oldValue.getClass()))
1161 {
1162 oldValue = Arrays.deepToString((Object[]) oldValue);
1163 }
1164 if (newValue != null && newValue.getClass().isArray() && Object[].class.isAssignableFrom(newValue.getClass()))
1165 {
1166 newValue = Arrays.deepToString((Object[]) newValue);
1167 }
1168
1169
1170 Throwable throwableHelper = new Throwable();
1171 StackTraceElement[] stackTraceElements = throwableHelper.getStackTrace();
1172 List<StackTraceElement> debugStackTraceElements = new LinkedList<StackTraceElement>();
1173
1174
1175 for (int i = skipStackTaceElements + 1; i < stackTraceElements.length; i++)
1176 {
1177 debugStackTraceElements.add(stackTraceElements[i]);
1178
1179 if (FacesServlet.class.getCanonicalName()
1180 .equals(stackTraceElements[i].getClassName()))
1181 {
1182
1183 break;
1184 }
1185 }
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195 Object[] debugInfo = new Object[4];
1196 debugInfo[0] = facesContext.getCurrentPhaseId();
1197 debugInfo[1] = oldValue;
1198 debugInfo[2] = newValue;
1199 debugInfo[3] = debugStackTraceElements;
1200
1201
1202 _getFieldDebugInfos(field).add(debugInfo);
1203 }
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213 public static boolean isEmpty(Object value)
1214 {
1215 if (value == null)
1216 {
1217 return true;
1218 }
1219 else if (value instanceof String)
1220 {
1221 if ( ((String)value).trim().length() <= 0 )
1222 {
1223 return true;
1224 }
1225 }
1226 else if (value instanceof Collection)
1227 {
1228 if ( ((Collection)value).isEmpty())
1229 {
1230 return true;
1231 }
1232 }
1233 else if (value.getClass().isArray())
1234 {
1235 if (java.lang.reflect.Array.getLength(value) <= 0)
1236 {
1237 return true;
1238 }
1239 }
1240 else if (value instanceof Map)
1241 {
1242 if ( ((Map)value).isEmpty())
1243 {
1244 return true;
1245 }
1246 }
1247 return false;
1248 }
1249
1250 }