You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@myfaces.apache.org by lu...@apache.org on 2009/12/15 23:38:13 UTC

svn commit: r891051 - in /myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean: Alias.java AliasBean.java AliasBeansScope.java

Author: lu4242
Date: Tue Dec 15 22:38:13 2009
New Revision: 891051

URL: http://svn.apache.org/viewvc?rev=891051&view=rev
Log:
TOMAHAWK-1473 Fix AliasBean hack on component binding to use the new api in jsf 2.0

Added:
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/Alias.java
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBean.java
    myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBeansScope.java

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/Alias.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/Alias.java?rev=891051&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/Alias.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/Alias.java Tue Dec 15 22:38:13 2009
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.aliasbean;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.context.FacesContext;
+import javax.faces.el.ValueBinding;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * A helper bean used by both AliasBean and AliasBeansScope components.
+ * <p>
+ * An Alias instance represents a single mapping from a "temporary" bean name
+ * to the real bean that temporary name should reference. When this alias
+ * is "activated" the temporary name is registered and when the alias is
+ * "deactivated" the temporary name is removed.
+ *
+ * @author Sylvain Vieujot (latest modification by $Author: skitching $)
+ * @version $Revision: 673833 $ $Date: 2008-07-03 16:58:05 -0500 (jue, 03 jul 2008) $
+ */
+
+class Alias {
+    static final Log log = LogFactory.getLog(Alias.class);
+    
+    private transient UIComponent _aliasComponent;
+    private String _aliasBeanExpression;
+    private String _valueExpression;
+    private transient boolean _active = false;
+    
+    private transient Object evaluatedExpression = null;
+
+    Alias(AliasBean aliasComponent){
+        this._aliasComponent = aliasComponent;
+    }
+
+    /**
+     * Define the temporary/transient name that will exist while this alias
+     * is "active" (in scope). This is usually a constant string.
+     */
+    void setAliasBeanExpression(String aliasBeanExpression){
+        this._aliasBeanExpression = aliasBeanExpression;
+    }
+    
+    /**
+     * Define the object that will be referenced by the temporary/transient
+     * name while it exists.
+     * <p>
+     * This can be a constant, but is more usually an EL expression. The value is
+     * recalculated each time this alias is "activated".
+     */
+    void setValueExpression(String valueExpression){
+        this._valueExpression = valueExpression;
+    }
+    
+    String getValueExpression(){
+        return _valueExpression;
+    }
+    
+    boolean isActive(){
+        return _active;
+    }
+    
+    String[] saveState(){
+        return new String[]{_aliasBeanExpression, _valueExpression};
+    }
+    
+    void restoreState(Object state){
+        String[] values = (String[]) state;
+        _aliasBeanExpression = values[0];
+        _valueExpression = values[1];
+    }
+    
+    private void computeEvaluatedExpression(FacesContext facesContext){
+        if( evaluatedExpression != null )
+            return;
+        
+        ValueExpression valueVB = null;
+        if (_valueExpression == null) {
+            valueVB = _aliasComponent.getValueExpression("value");
+            _valueExpression = valueVB.getExpressionString();
+        }
+
+        if( valueVB == null ){
+            if( _valueExpression.startsWith("#{") ){
+                valueVB = facesContext.getApplication().getExpressionFactory()
+                    .createValueExpression(facesContext.getELContext(),                            
+                            _valueExpression,
+                            Object.class);
+                evaluatedExpression = valueVB.getValue(facesContext.getELContext());
+            }else{
+                evaluatedExpression = _valueExpression;
+            }
+        }else{
+            evaluatedExpression = valueVB.getValue(facesContext.getELContext());
+        }
+    }
+
+    /**
+     * Activate this alias (ie create the temporary name).
+     */
+    void make(FacesContext facesContext){
+        if( _active )
+            return;
+
+        ValueExpression aliasVB;
+        if (_aliasBeanExpression == null) {
+            aliasVB = _aliasComponent.getValueExpression("alias");
+            if( aliasVB == null )
+                return;
+            _aliasBeanExpression = aliasVB.getExpressionString();
+            if( _aliasBeanExpression == null )
+                return;
+        } else {
+            aliasVB = facesContext.getApplication().getExpressionFactory().
+                createValueExpression(facesContext.getELContext(),_aliasBeanExpression,Object.class);
+        }
+
+        computeEvaluatedExpression( facesContext );
+        
+        aliasVB.setValue(facesContext.getELContext(), evaluatedExpression);
+        _active = true;
+
+        log.debug("makeAlias: " + _valueExpression + " = " + _aliasBeanExpression);
+    }
+    
+    /**
+     * Deactivate this alias (ie remove the temporary name).
+     */
+    void remove(FacesContext facesContext){
+        _active = false;
+        if( evaluatedExpression == null )
+            return;
+        
+        evaluatedExpression = null;
+
+        log.debug("removeAlias: " + _valueExpression + " != " + _aliasBeanExpression);
+        ValueExpression aliasVB = _aliasComponent.getValueExpression("alias");
+        if( aliasVB != null )
+            aliasVB.setValue(facesContext.getELContext(), null);
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBean.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBean.java?rev=891051&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBean.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBean.java Tue Dec 15 22:38:13 2009
@@ -0,0 +1,397 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.aliasbean;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import javax.el.ValueExpression;
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIComponentBase;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.FacesEvent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperties;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFProperty;
+import org.apache.myfaces.shared_tomahawk.component.BindingAware;
+import org.apache.myfaces.shared_tomahawk.util.RestoreStateUtils;
+import org.apache.myfaces.shared_tomahawk.util._ComponentUtils;
+
+/**
+ * The aliasBean tag allows you to create a temporary name for a real bean.
+ * The temporary name exists (is visible) only to the children of the aliasBean.
+ * <p>
+ * One use of this feature is to pass "parameters" from an including page to an
+ * included one. The included page can use any name it desires for beans it needs to
+ * reference, and the including page can then use aliasBean to make those names
+ * refer to the beans it wishes to "pass" as parameters.
+ * </p>
+ * <p>
+ * Suppose you have a block of components you use often but with different beans. You
+ * can create a separate JSP page (or equivalent) containing these beans, where the
+ * value-bindings refer to some fictive bean name. Document these names as the required
+ * "parameters" for this JSP page. Wherever you wish to use this block you then declare
+ * an alias component mapping each of these "parameters" to whatever beans (or literal
+ * values) you really want to apply the block to, then use jsp:include (or equivalent)
+ * to include the reusable block of components.
+ * </p>
+ * <p>
+ * Note, however, that AliasBean does not work for component bindings; JSF1.1
+ * just has no mechanism available to set up the alias during the "restore view"
+ * phase while the bindings of its children are being re-established, and then
+ * remove the alias after the child bindings are done.
+ * </p>
+ * <p>
+ * As a special case, if this component's direct parent is an AliasBeansScope
+ * then the alias (temporary name) is active until the end of the parent
+ * component, rather than the end of this component.
+ * </p>
+ *
+ * @author Sylvain Vieujot (latest modification by $Author: lu4242 $)
+ * @version $Revision: 690079 $ $Date: 2008-08-28 21:58:51 -0500 (jue, 28 ago 2008) $
+ */
+@JSFComponent(
+        name="t:aliasBean",
+        tagClass = "org.apache.myfaces.custom.aliasbean.AliasBeanTag",
+        tagHandler = "org.apache.myfaces.custom.aliasbean.AliasBeanTagHandler")
+@JSFJspProperties(properties={
+        @JSFJspProperty(
+                name = "rendered",
+                returnType = "boolean", 
+                tagExcluded = true),
+        @JSFJspProperty(
+                name = "binding",
+                returnType = "java.lang.String",
+                tagExcluded = true)
+                })
+public class AliasBean extends UIComponentBase implements BindingAware
+{
+    private static final Log log = LogFactory.getLog(AliasBean.class);
+
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.AliasBean";
+    public static final String COMPONENT_FAMILY = "javax.faces.Data";
+
+    private Alias alias;
+    
+    // Indicates whether withinScope has been initialised or not.
+    private boolean scopeSearched = false;
+    
+    // True if this is a direct child of an AliasBeansScope component.
+    private boolean withinScope;
+
+    private transient FacesContext _context = null;
+
+    public AliasBean()
+    {
+        alias = new Alias(this);
+    }
+
+    public String getFamily()
+    {
+        return COMPONENT_FAMILY;
+    }
+
+    public String getRendererType() {
+        return null;
+    }
+
+    /**
+     * Define the "fictive" name which will be visible to the children
+     * of this component as an alias to the "real" object specified
+     * by the value attribute of this component.
+     *
+     * @param aliasBeanExpression
+     */
+    @JSFProperty
+    public void setAlias(String aliasBeanExpression)
+    {
+        alias.setAliasBeanExpression(aliasBeanExpression);
+    }
+
+    /**
+     * The existing value that the alias can be set to. This can be 
+     * a literal string (like "toto") or a reference to an existing 
+     * bean (like "#{myBean.member1}").
+     * 
+     */
+    @JSFProperty
+    public String getValue()
+    {
+        String valueExpression = alias.getValueExpression();
+        if (valueExpression != null)
+            return valueExpression;
+
+        // Normally, this component will have no value, because the setValue method always
+        // passes that data on to the alias instead. However it is possible for someone
+        // to use f:attribute (or other mechanism?) to set the value instead. So when the
+        // alias has no value, look for it there.
+        ValueExpression vb = getValueExpression("value");
+        return vb != null ?  (String) vb.getValue(getFacesContext().getELContext()) : null;
+    }
+
+    public void setValue(String valueExpression)
+    {
+        alias.setValueExpression(valueExpression);
+    }
+
+    public Object saveState(FacesContext context)
+    {
+        log.debug("saveState");
+
+        _context = context;
+
+        return new Object[]{super.saveState(context), alias.saveState()};
+    }
+
+    public void restoreState(FacesContext context, Object state)
+    {
+        log.debug("restoreState");
+
+        _context = context;
+
+        Object values[] = (Object[]) state;
+        super.restoreState(context, values[0]);
+        alias.restoreState(values[1]);
+    }
+
+    public Object processSaveState(FacesContext context)
+    {
+        if (context == null)
+            throw new NullPointerException("context");
+        if (isTransient())
+            return null;
+
+        makeAlias(context);
+
+        Map facetMap = null;
+        for (Iterator it = getFacets().entrySet().iterator(); it.hasNext();)
+        {
+            Map.Entry entry = (Map.Entry) it.next();
+            if (facetMap == null)
+                facetMap = new HashMap();
+            UIComponent component = (UIComponent) entry.getValue();
+            if (!component.isTransient())
+            {
+                facetMap.put(entry.getKey(), component.processSaveState(context));
+            }
+        }
+        List childrenList = null;
+        if (getChildCount() > 0)
+        {
+            for (Iterator it = getChildren().iterator(); it.hasNext();)
+            {
+                UIComponent child = (UIComponent) it.next();
+                if (!child.isTransient())
+                {
+                    if (childrenList == null)
+                        childrenList = new ArrayList(getChildCount());
+                    childrenList.add(child.processSaveState(context));
+                }
+            }
+        }
+
+        removeAlias(context);
+
+        return new Object[]{saveState(context), facetMap, childrenList};
+    }
+
+    public void processRestoreState(FacesContext context, Object state)
+    {
+        if (context == null)
+            throw new NullPointerException("context");
+        Object myState = ((Object[]) state)[0];
+
+        restoreState(context, myState);
+        makeAlias(context);
+
+        Map facetMap = (Map) ((Object[]) state)[1];
+        List childrenList = (List) ((Object[]) state)[2];
+        for (Iterator it = getFacets().entrySet().iterator(); it.hasNext();)
+        {
+            Map.Entry entry = (Map.Entry) it.next();
+            Object facetState = facetMap.get(entry.getKey());
+            if (facetState != null)
+            {
+                ((UIComponent) entry.getValue()).processRestoreState(context, facetState);
+            }
+            else
+            {
+                context.getExternalContext().log("No state found to restore facet " + entry.getKey());
+            }
+        }
+        if (getChildCount() > 0)
+        {
+            int idx = 0;
+            for (Iterator it = getChildren().iterator(); it.hasNext();)
+            {
+                UIComponent child = (UIComponent) it.next();
+                Object childState = childrenList.get(idx++);
+                if (childState != null)
+                {
+                    child.processRestoreState(context, childState);
+                }
+                else
+                {
+                    context.getExternalContext().log("No state found to restore child of component " + getId());
+                }
+            }
+        }
+
+        removeAlias(context);
+    }
+
+    public void processValidators(FacesContext context)
+    {
+        if (withinScope)
+            return;
+
+        log.debug("processValidators");
+        makeAlias(context);
+        super.processValidators(context);
+        removeAlias(context);
+    }
+
+    public void processDecodes(FacesContext context)
+    {
+        log.debug("processDecodes");
+        if (withinScope)
+        {
+            if (! alias.isActive())
+                makeAlias(context);
+
+            super.processDecodes(context);
+            return;
+        }
+
+        makeAlias(context);
+        super.processDecodes(context);
+        removeAlias(context);
+    }
+
+    public void processUpdates(FacesContext context)
+    {
+        if (withinScope)
+            return;
+
+        log.debug("processUpdates");
+        makeAlias(context);
+        super.processUpdates(context);
+        removeAlias(context);
+    }
+
+
+  public void encodeBegin(FacesContext context) throws IOException {
+    makeAlias(context);
+  }
+
+
+  public void encodeEnd(FacesContext context) throws IOException {
+    removeAlias();
+  }
+
+  public void queueEvent(FacesEvent event)
+    {
+        super.queueEvent(new FacesEventWrapper(event, this));
+    }
+
+    public void broadcast(FacesEvent event) throws AbortProcessingException
+    {
+        makeAlias();
+
+        if (event instanceof FacesEventWrapper)
+        {
+            FacesEvent originalEvent = ((FacesEventWrapper) event).getWrappedFacesEvent();
+            originalEvent.getComponent().broadcast(originalEvent);
+        }
+        else
+        {
+            super.broadcast(event);
+        }
+
+        removeAlias();
+    }
+
+    void makeAlias(FacesContext context)
+    {
+        _context = context;
+        makeAlias();
+    }
+
+    private void makeAlias()
+    {
+        if (! scopeSearched)
+        {
+            withinScope = getParent() instanceof AliasBeansScope;
+            if (withinScope)
+            {
+                AliasBeansScope aliasScope = (AliasBeansScope) getParent();
+                aliasScope.addAlias(alias);
+            }
+            scopeSearched = true;
+        }
+        alias.make(_context);
+    }
+
+    void removeAlias(FacesContext context)
+    {
+        _context = context;
+        removeAlias();
+    }
+
+    private void removeAlias()
+    {
+        if (! withinScope)
+            alias.remove(_context);
+    }
+
+
+    public void handleBindings()
+    {
+        makeAlias(getFacesContext());
+
+        RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(getFacesContext(),this,true);
+
+        removeAlias(getFacesContext());
+    }
+
+    @Override
+    public boolean visitTree(VisitContext context, VisitCallback callback)
+    {
+        makeAlias(getFacesContext());
+        try
+        {
+            return super.visitTree(context, callback);
+        }
+        finally
+        {
+            removeAlias(getFacesContext());
+        }
+    }
+}

Added: myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBeansScope.java
URL: http://svn.apache.org/viewvc/myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBeansScope.java?rev=891051&view=auto
==============================================================================
--- myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBeansScope.java (added)
+++ myfaces/tomahawk/trunk/core20/src/main/java/org/apache/myfaces/custom/aliasbean/AliasBeansScope.java Tue Dec 15 22:38:13 2009
@@ -0,0 +1,308 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.myfaces.custom.aliasbean;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.io.IOException;
+
+import javax.faces.component.UIComponent;
+import javax.faces.component.UIComponentBase;
+import javax.faces.component.visit.VisitCallback;
+import javax.faces.component.visit.VisitContext;
+import javax.faces.context.FacesContext;
+import javax.faces.event.AbortProcessingException;
+import javax.faces.event.FacesEvent;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFComponent;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperties;
+import org.apache.myfaces.buildtools.maven2.plugin.builder.annotation.JSFJspProperty;
+import org.apache.myfaces.shared_tomahawk.util.RestoreStateUtils;
+import org.apache.myfaces.shared_tomahawk.component.BindingAware;
+
+/**
+ * Holds several aliases that are configured by aliasBean tags.
+ * <p>
+ * The aliasBean tag must enclose all the components that are within the scope
+ * of the alias. When multiple aliasas are defined, this makes the page structure
+ * very clumsy; for example defining 5 aliases means the content must be nested
+ * 5 indentation levels deep. This tag instead allows the content block to be
+ * wrapped in just one AliasBeansScope tag, and then have AliasBean tags with
+ * empty bodies added as direct children of this component. The scope of the AliasBean
+ * tag still starts when the tag begins, but instead of ending when the tag ends
+ * the scope of the nested AliasBean tags extends to the end of this component.
+ * </p>
+ * 
+ * @author Sylvain Vieujot (latest modification by $Author: lu4242 $)
+ * @version $Revision: 690079 $ $Date: 2008-08-28 21:58:51 -0500 (jue, 28 ago 2008) $
+ */
+@JSFComponent(
+        name = "t:aliasBeansScope",
+        tagClass = "org.apache.myfaces.custom.aliasbean.AliasBeansScopeTag",
+        tagHandler = "org.apache.myfaces.custom.aliasbean.AliasBeansScopeTagHandler")
+@JSFJspProperties(properties={
+        @JSFJspProperty(
+                name = "rendered",
+                returnType = "boolean", 
+                tagExcluded = true),
+        @JSFJspProperty(
+                name = "binding",
+                returnType = "java.lang.String",
+                tagExcluded = true)
+                })
+public class AliasBeansScope extends UIComponentBase implements BindingAware
+{
+    static final Log log = LogFactory.getLog(AliasBeansScope.class);
+
+    public static final String COMPONENT_TYPE = "org.apache.myfaces.AliasBeansScope";
+    public static final String COMPONENT_FAMILY = "javax.faces.Data";
+
+    private ArrayList _aliases = new ArrayList();
+    transient FacesContext _context = null;
+
+    void addAlias(Alias alias)
+    {
+        _aliases.add(alias);
+    }
+
+    public String getFamily()
+    {
+        return COMPONENT_FAMILY;
+    }
+
+    public String getRendererType() {
+      return null;
+    }
+
+  public Object saveState(FacesContext context)
+    {
+        log.debug("saveState");
+        _context = context;
+
+        return super.saveState(context);
+    }
+
+    public void restoreState(FacesContext context, Object state)
+    {
+        log.debug("restoreState");
+        _context = context;
+
+        super.restoreState(context, state);
+    }
+
+    public Object processSaveState(FacesContext context)
+    {
+        if (context == null)
+            throw new NullPointerException("context");
+        if (isTransient())
+            return null;
+
+        makeAliases(context);
+
+        Map facetMap = null;
+        for (Iterator it = getFacets().entrySet().iterator(); it.hasNext();)
+        {
+            Map.Entry entry = (Map.Entry) it.next();
+            if (facetMap == null)
+                facetMap = new HashMap();
+            UIComponent component = (UIComponent) entry.getValue();
+            if (!component.isTransient())
+            {
+                facetMap.put(entry.getKey(), component.processSaveState(context));
+            }
+        }
+
+        List childrenList = null;
+        if (getChildCount() > 0)
+        {
+            for (Iterator it = getChildren().iterator(); it.hasNext();)
+            {
+                UIComponent child = (UIComponent) it.next();
+                if (!child.isTransient())
+                {
+                    if (childrenList == null)
+                        childrenList = new ArrayList(getChildCount());
+                    childrenList.add(child.processSaveState(context));
+                }
+            }
+        }
+
+        removeAliases(context);
+
+        return new Object[]{saveState(context), facetMap, childrenList};
+    }
+
+    public void processRestoreState(FacesContext context, Object state)
+    {
+        if (context == null)
+            throw new NullPointerException("context");
+        Object myState = ((Object[]) state)[0];
+
+        restoreState(context, myState);
+
+        makeAliases(context);
+
+        Map facetMap = (Map) ((Object[]) state)[1];
+
+        for (Iterator it = getFacets().entrySet().iterator(); it.hasNext();)
+        {
+            Map.Entry entry = (Map.Entry) it.next();
+            Object facetState = facetMap.get(entry.getKey());
+            if (facetState != null)
+            {
+                ((UIComponent) entry.getValue()).processRestoreState(context, facetState);
+            }
+            else
+            {
+                context.getExternalContext().log("No state found to restore facet " + entry.getKey());
+            }
+        }
+
+        List childrenList = (List) ((Object[]) state)[2];
+        if (getChildCount() > 0)
+        {
+            int idx = 0;
+            for (Iterator it = getChildren().iterator(); it.hasNext();)
+            {
+                UIComponent child = (UIComponent) it.next();
+                Object childState = childrenList.get(idx++);
+                if (childState != null)
+                {
+                    child.processRestoreState(context, childState);
+                }
+                else
+                {
+                    context.getExternalContext().log("No state found to restore child of component " + getId());
+                }
+            }
+        }
+
+        removeAliases(context);
+    }
+
+    public void processValidators(FacesContext context)
+    {
+        log.debug("processValidators");
+        makeAliases(context);
+        super.processValidators(context);
+        removeAliases(context);
+    }
+
+    public void processDecodes(FacesContext context)
+    {
+        log.debug("processDecodes");
+        makeAliases(context);
+        super.processDecodes(context);
+        removeAliases(context);
+    }
+
+    public void processUpdates(FacesContext context)
+    {
+        log.debug("processUpdates");
+        makeAliases(context);
+        super.processUpdates(context);
+        removeAliases(context);
+    }
+
+    public void encodeBegin(FacesContext context) throws IOException
+    {
+        log.debug("encodeBegin");
+        makeAliases(context);
+    }
+
+    public void encodeEnd(FacesContext context)
+    {
+        log.debug("encodeEnd");
+        removeAliases(context);
+    }
+
+    public void queueEvent(FacesEvent event)
+    {
+        super.queueEvent(new FacesEventWrapper(event, this));
+    }
+
+    public void broadcast(FacesEvent event) throws AbortProcessingException
+    {
+        makeAliases();
+
+        if (event instanceof FacesEventWrapper)
+        {
+            FacesEvent originalEvent = ((FacesEventWrapper) event).getWrappedFacesEvent();
+            originalEvent.getComponent().broadcast(originalEvent);
+        }
+        else
+        {
+            super.broadcast(event);
+        }
+
+        removeAliases();
+    }
+
+    void makeAliases(FacesContext context)
+    {
+        _context = context;
+        makeAliases();
+    }
+
+    private void makeAliases()
+    {
+        for (Iterator i = _aliases.iterator(); i.hasNext();)
+            ((Alias) i.next()).make(_context);
+    }
+
+    void removeAliases(FacesContext context)
+    {
+        _context = context;
+        removeAliases();
+    }
+
+    private void removeAliases()
+    {
+        for (Iterator i = _aliases.iterator(); i.hasNext();)
+            ((Alias) i.next()).remove(_context);
+    }
+
+    public void handleBindings()
+    {
+        makeAliases(getFacesContext());
+
+        RestoreStateUtils.recursivelyHandleComponentReferencesAndSetValid(getFacesContext(), this, true);
+
+        removeAliases(getFacesContext());
+    }
+
+    @Override
+    public boolean visitTree(VisitContext context, VisitCallback callback)
+    {
+        makeAliases(getFacesContext());
+        try
+        {
+            return super.visitTree(context, callback);
+        }
+        finally
+        {
+            removeAliases(getFacesContext());
+        }
+    }
+}