01: package org.apache.myfaces.shared_impl.util;
02:
03: import java.lang.reflect.Method;
04: import java.util.Iterator;
05:
06: import javax.el.ValueExpression;
07: import javax.faces.component.UIComponent;
08: import javax.faces.component.UIInput;
09: import javax.faces.context.FacesContext;
10:
11: import org.apache.commons.logging.Log;
12: import org.apache.commons.logging.LogFactory;
13:
14: /**
15: * @author Martin Marinschek (latest modification by $Author: grantsmith $)
16: * @version $Revision: 169655 $ $Date: 2005-05-11 18:45:06 +0200 (Mi, 11 Mai 2005) $
17: */
18: public class RestoreStateUtils {
19: private static Log log = LogFactory.getLog(RestoreStateUtils.class);
20:
21: /**
22: * Walk the component tree, executing any component-bindings to reattach
23: * components to their backing beans. Also, any UIInput component is
24: * marked as Valid.
25: * <p>
26: * Note that this method effectively breaks encapsulation; instead of
27: * asking each component to update itself and its children, this
28: * method just reaches into each component. That makes it impossible
29: * for any component to customise its behaviour at this point.
30: * <p>
31: * This has been filed as an issue against the spec. Until this
32: * issue is resolved, we'll add a new marker-interface for components
33: * to allow them to define their interest in handling children bindings themselves.
34: */
35: public static void recursivelyHandleComponentReferencesAndSetValid(
36: FacesContext facesContext, UIComponent parent) {
37: recursivelyHandleComponentReferencesAndSetValid(facesContext,
38: parent, false);
39: }
40:
41: public static void recursivelyHandleComponentReferencesAndSetValid(
42: FacesContext facesContext, UIComponent parent,
43: boolean forceHandle) {
44: Method handleBindingsMethod = getBindingMethod(parent);
45:
46: if (handleBindingsMethod != null && !forceHandle) {
47: try {
48: handleBindingsMethod.invoke(parent, new Object[] {});
49: } catch (Throwable th) {
50: log.error(
51: "Exception while invoking handleBindings on component with client-id:"
52: + parent.getClientId(facesContext), th);
53: }
54: } else {
55: for (Iterator it = parent.getFacetsAndChildren(); it
56: .hasNext();) {
57: UIComponent component = (UIComponent) it.next();
58:
59: ValueExpression binding = component
60: .getValueExpression("binding"); //TODO: constant
61: if (binding != null) {
62: binding.setValue(facesContext.getELContext(),
63: component);
64: }
65:
66: if (component instanceof UIInput) {
67: ((UIInput) component).setValid(true);
68: }
69:
70: recursivelyHandleComponentReferencesAndSetValid(
71: facesContext, component);
72: }
73: }
74: }
75:
76: /**This is all a hack to work around a spec-bug which will be fixed in JSF2.0
77: *
78: * @param parent
79: * @return true if this component is bindingAware (e.g. aliasBean)
80: */
81: private static Method getBindingMethod(UIComponent parent) {
82: Class[] clazzes = parent.getClass().getInterfaces();
83:
84: for (int i = 0; i < clazzes.length; i++) {
85: Class clazz = clazzes[i];
86:
87: if (clazz.getName().indexOf("BindingAware") != -1) {
88: try {
89: return parent.getClass().getMethod(
90: "handleBindings", new Class[] {});
91: } catch (NoSuchMethodException e) {
92: // return
93: }
94: }
95: }
96:
97: return null;
98: }
99: }
|