Package org.apache.beehive.netui.pageflow

Source Code of org.apache.beehive.netui.pageflow.SharedFlowController

/*
* Copyright 2004 The Apache Software Foundation.
*
* Licensed 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.
*
* $Header:$
*/
package org.apache.beehive.netui.pageflow;

import org.apache.beehive.netui.pageflow.handler.Handlers;
import org.apache.beehive.netui.pageflow.handler.StorageHandler;
import org.apache.beehive.netui.pageflow.internal.InternalConstants;
import org.apache.beehive.netui.util.internal.cache.ClassLevelCache;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


/**
* <p>
* Base "shared flow" class for controller logic, exception handlers, and state that can be shared by any number of page
* flows.  A shared flow is <i>not</i> a page flow; it is used by page flows, but never becomes the "current page flow"
* (see {@link PageFlowController} for information on page flows and the "current page flow").
* The class is configured through the
* {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller} annotation.
* </p>
*
* <p>
* A shared flow comes into existance in one of two ways:
* <ul>
*     <li>
*         A page flow is hit, and the page flow refers to the shared flow in its
*         {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#sharedFlowRefs sharedFlowRefs}
*         annotation attribute, or
*     </li>
*     <li>
*         Any page flow is hit, and the <code>&lt;default-shared-flow-refs&gt;</code> element in
*         /WEB-INF/beehive-netui-config.xml declares that this shared flow will be used by all page flows in the web
*         application.
*     </li>
* </ul>
* When a shared flow is created, it is stored in the user session.  It is only removed through a call to
* {@link #remove} or through a call to {@link PageFlowUtils#removeSharedFlow}.
* </p>
*
* <p>
* Shared flow actions are defined with <i>action methods</i> or <i>action annotations</i> that determine the next URI
* to be displayed, after optionally performing arbitrary logic.  A page or page flow can raise a shared flow action
* using the pattern <code>"</code><i>shared-flow-name</i><code>.</code><i>action-name</i><code>"</code>.  The shared
* flow name is the one chosen by the page flow
* in {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SharedFlowRef#name name}
* on {@link org.apache.beehive.netui.pageflow.annotations.Jpf.SharedFlowRef &#64;Jpf.SharedFlowRef}.
* </p>
*
* <p>
* A referenced shared flow gets the chance to handle any uncaught page flow exception.  It declares its exception
* handling through {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller#catches catches}
* on {@link org.apache.beehive.netui.pageflow.annotations.Jpf.Controller &#64;Jpf.Controller}.
* </p>
*
* <p>
* Properties in the current shared flow instance can be accessed from JSP 2.0-style expressions like this one:
* <code>${sharedFlow.</code><i>sharedFlowName</i><code>.someProperty}</code>.
* </p>
*
* <p>
* There may only be one shared flow in any package.
* </p>
*
* @see PageFlowController
*/
public abstract class SharedFlowController
        extends FlowController
        implements PageFlowConstants
{
    private static final String CACHED_INFO_KEY = "cachedInfo";
   
    /**
     * Get the Struts module path for actions in this shared flow.
     *
     * @return the Struts module path for actions in this shared flow.
     */
    public String getModulePath()
    {
        ClassLevelCache cache = ClassLevelCache.getCache( getClass() );
        String modulePath = ( String ) cache.getCacheObject( CACHED_INFO_KEY );
       
        if ( modulePath == null )
        {
            String className = getClass().getName();
            int lastDot = className.lastIndexOf( '.' );
            assert lastDot != -1 : className;
            className = className.substring( 0, lastDot );
            modulePath = "/-" + className.replace( '.', '/' );
            cache.setCacheObject( CACHED_INFO_KEY, modulePath );
        }
       
        return modulePath;
    }
   
    /**
     * Store this object in the user session, in the appropriate place.  Used by the framework; normally should not be
     * called directly.
     */
    public void persistInSession( HttpServletRequest request, HttpServletResponse response )
    {
        StorageHandler sh = Handlers.get( getServletContext() ).getStorageHandler();
        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
        RequestContext rc = new RequestContext( unwrappedRequest, null );
        sh.setAttribute( rc, InternalConstants.SHARED_FLOW_ATTR_PREFIX + getClass().getName(), this );
    }
   
    /**
     * Ensures that any changes to this object will be replicated in a cluster (for failover),
     * even if the replication scheme uses a change-detection algorithm that relies on
     * HttpSession.setAttribute to be aware of changes.  Note that this method is used by the framework
     * and does not need to be called explicitly in most cases.
     *
     * @param request the current HttpServletRequest
     */
    public void ensureFailover( HttpServletRequest request )
    {
        StorageHandler sh = Handlers.get( getServletContext() ).getStorageHandler();
        HttpServletRequest unwrappedRequest = PageFlowUtils.unwrapMultipart( request );
        RequestContext rc = new RequestContext( unwrappedRequest, null );
        sh.ensureFailover( rc, InternalConstants.SHARED_FLOW_ATTR_PREFIX + getClass().getName(), this );
    }
   
    /**
     * Get the URI.
     * @return <code>null</code>, as this object is not URL-addressible.
     */
    public String getURI()
    {
        return "/";
    }
   
    /**
     * Get the display name.  The display name for a shared flow is simply the class name.
     * @return the name of the shared flow class.
     */
    public String getDisplayName()
    {
        return getClass().getName();
    }
   
    /**
     * Get a legacy PreviousPageInfo.
     * @deprecated This method will be removed without replacement in a future release.
     */
    public PreviousPageInfo getPreviousPageInfoLegacy( PageFlowController curJpf, HttpServletRequest request )
    {
        assert curJpf != null;
        return curJpf.getCurrentPageInfo();       
    }
   
    /**
     * Store information about recent pages displayed.  This is a framework-invoked method that should not normally be
     * called directly.
     */
    public void savePreviousPageInfo( ActionForward forward, ActionForm form, ActionMapping mapping,
                                      HttpServletRequest request, ServletContext servletContext,
                                      boolean isSpecialForward )
    {
        //
        // Special case: if the given forward has a path to a page in the current pageflow, let that pageflow save
        // the info on this page.  Otherwise, don't ever save any info on what we're forwarding to.
        //
        if ( ! isSpecialForward && forward != null // i.e., it's a straight Forward to a path, not a navigateTo, etc.
        {
            PageFlowController currentJpf = PageFlowUtils.getCurrentPageFlow( request, getServletContext() );
           
            if ( currentJpf != null )
            {
                if ( forward.getContextRelative() && forward.getPath().startsWith( currentJpf.getModulePath() ) )
                {
                    currentJpf.savePreviousPageInfo( forward, form, mapping, request, servletContext, isSpecialForward );
                }
            }
        }
    }

    /**
     * Store information about the most recent action invocation.  This is a framework-invoked method that should not
     * normally be called directly
     */
    void savePreviousActionInfo( ActionForm form, HttpServletRequest request, ActionMapping mapping,
                                 ServletContext servletContext )
    {
        //
        // Save this previous-action info in the *current page flow*.
        //
        PageFlowController currentJpf = PageFlowUtils.getCurrentPageFlow( request, getServletContext() );
        if ( currentJpf != null ) currentJpf.savePreviousActionInfo( form, request, mapping, servletContext );
    }

    /**
     * Remove this instance from the session.  When inside a shared flow action, {@link #remove} may be called instead.
     */
    protected synchronized void removeFromSession( HttpServletRequest request )
    {
        PageFlowUtils.removeSharedFlow( getClass().getName(), request );
    }
}
TOP

Related Classes of org.apache.beehive.netui.pageflow.SharedFlowController

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.