All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.struts2.jsf.RestoreViewInterceptor Maven / Gradle / Ivy

There is a newer version: 2.3.37
Show newest version
/*
 * $Id: RestoreViewInterceptor.java 651946 2008-04-27 13:41:38Z apetrelli $
 *
 * 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.struts2.jsf;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.Iterator;

import javax.faces.FacesException;
import javax.faces.application.Application;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UIViewRoot;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.el.ValueBinding;
import javax.faces.event.PhaseId;

/**
 * Restores the view or component tree
 */
public class RestoreViewInterceptor extends FacesInterceptor {

    private static final long serialVersionUID = -1500785113037140668L;

    /**
     * Restore View (JSF.2.2.1)
     *
     * @param viewId
     *            The view id
     * @param facesContext
     *            The faces context
     * @return true, if immediate rendering should occur
     */
    protected boolean executePhase(String viewId, FacesContext facesContext) {
        boolean skipFurtherProcessing = false;
        if (log.isTraceEnabled())
            log.trace("entering restoreView");

        informPhaseListenersBefore(facesContext, PhaseId.RESTORE_VIEW);

        try {
            if (isResponseComplete(facesContext, "restoreView", true)) {
                // have to skips this phase
                return true;
            }
            if (shouldRenderResponse(facesContext, "restoreView", true)) {
                skipFurtherProcessing = true;
            }

            ExternalContext externalContext = facesContext.getExternalContext();
            String defaultSuffix = externalContext
                    .getInitParameter(ViewHandler.DEFAULT_SUFFIX_PARAM_NAME);
            String suffix = defaultSuffix != null ? defaultSuffix
                    : ViewHandler.DEFAULT_SUFFIX;
            if (viewId != null) {
                viewId += suffix;
            }

            if (viewId == null) {
                if (!externalContext.getRequestServletPath().endsWith("/")) {
                    try {
                        externalContext.redirect(externalContext
                                .getRequestServletPath()
                                + "/");
                        facesContext.responseComplete();
                        return true;
                    } catch (IOException e) {
                        throw new FacesException("redirect failed", e);
                    }
                }
            }

            Application application = facesContext.getApplication();
            ViewHandler viewHandler = application.getViewHandler();

            // boolean viewCreated = false;
            UIViewRoot viewRoot = viewHandler.restoreView(facesContext, viewId);
            if (viewRoot == null) {
                viewRoot = viewHandler.createView(facesContext, viewId);
                viewRoot.setViewId(viewId);
                facesContext.renderResponse();
                // viewCreated = true;
            }

            facesContext.setViewRoot(viewRoot);

            /*
             * This section has been disabled because it causes some bug. Be
             * careful if you need to re-enable it. Furthermore, for an unknown
             * reason, it seems that by default it is executed (i.e.
             * log.isTraceEnabled() is true). Bug example : This traceView
             * causes DebugUtil.printComponent to print all the attributes of
             * the view components. And if you have a data table within an
             * aliasBean, this causes the data table to initialize it's value
             * attribute while the alias isn't set. So, the value initializes
             * with an UIData.EMPTY_DATA_MODEL, and not with the aliased one.
             * But as it's initialized, it will not try to get the value from
             * the ValueBinding next time it needs to. I expect this to cause
             * more similar bugs. TODO : Completely remove or be SURE by default
             * it's not executed, and it has no more side-effects.
             *
             * if (log.isTraceEnabled()) { //Note: DebugUtils Logger must also
             * be in trace level DebugUtils.traceView(viewCreated ? "Newly
             * created view" : "Restored view"); }
             */

            if (facesContext.getExternalContext().getRequestParameterMap()
                    .isEmpty()) {
                // no POST or query parameters --> set render response flag
                facesContext.renderResponse();
            }

            recursivelyHandleComponentReferencesAndSetValid(facesContext,
                    viewRoot);
        } finally {
            informPhaseListenersAfter(facesContext, PhaseId.RESTORE_VIEW);
        }

        if (isResponseComplete(facesContext, "restoreView", false)
                || shouldRenderResponse(facesContext, "restoreView", false)) {
            // since this phase is completed we don't need to return right away
            // even if the response is completed
            skipFurtherProcessing = true;
        }

        if (!skipFurtherProcessing && log.isTraceEnabled())
            log.trace("exiting restoreView ");
        return skipFurtherProcessing;
    }

    /**
     * Walk the component tree, executing any component-bindings to reattach
     * components to their backing beans. Also, any UIInput component is marked
     * as Valid.
     * 

* Note that this method effectively breaks encapsulation; instead of asking * each component to update itself and its children, this method just * reaches into each component. That makes it impossible for any component * to customise its behaviour at this point. *

* This has been filed as an issue against the spec. Until this issue is * resolved, we'll add a new marker-interface for components to allow them * to define their interest in handling children bindings themselves. */ protected void recursivelyHandleComponentReferencesAndSetValid( FacesContext facesContext, UIComponent parent) { recursivelyHandleComponentReferencesAndSetValid(facesContext, parent, false); } protected void recursivelyHandleComponentReferencesAndSetValid( FacesContext facesContext, UIComponent parent, boolean forceHandle) { Method handleBindingsMethod = getBindingMethod(parent); if (handleBindingsMethod != null && !forceHandle) { try { handleBindingsMethod.invoke(parent, new Object[] {}); } catch (Throwable th) { log.error( "Exception while invoking handleBindings on component with client-id:" + parent.getClientId(facesContext), th); } } else { for (Iterator it = parent.getFacetsAndChildren(); it.hasNext();) { UIComponent component = (UIComponent) it.next(); ValueBinding binding = component.getValueBinding("binding"); // TODO: // constant if (binding != null && !binding.isReadOnly(facesContext)) { binding.setValue(facesContext, component); } if (component instanceof UIInput) { ((UIInput) component).setValid(true); } recursivelyHandleComponentReferencesAndSetValid(facesContext, component); } } } /** * This is all a hack to work around a spec-bug which will be fixed in * JSF2.0 * * @param parent * @return true if this component is bindingAware (e.g. aliasBean) */ private static Method getBindingMethod(UIComponent parent) { Class[] clazzes = parent.getClass().getInterfaces(); for (int i = 0; i < clazzes.length; i++) { Class clazz = clazzes[i]; if (clazz.getName().indexOf("BindingAware") != -1) { try { return parent.getClass().getMethod("handleBindings", new Class[] {}); } catch (NoSuchMethodException e) { // return } } } return null; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy