View Javadoc

1   /**
2    * Copyright 2005-2006 the original author or authors.
3    *
4    * Licensed under the Gnu General Pubic License, Version 2.0 (the
5    * "License"); you may not use this file except in compliance with
6    * the License. You may obtain a copy of the License at
7    *
8    *      http://www.opensource.org/licenses/gpl-license.php
9    *
10   * This program is distributed in the hope that it will be useful,
11   * but WITHOUT ANY WARRANTY; without even the implied warranty of
12   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13   * See the Gnu General Public License for more details.
14   */
15  package org.figure8.join.control;
16  
17  import org.apache.struts.action.Action;
18  import org.apache.struts.action.ActionForm;
19  import org.apache.struts.action.ActionForward;
20  import org.apache.struts.action.ActionMapping;
21  
22  import javax.servlet.http.HttpSession;
23  import javax.servlet.http.HttpServletRequest;
24  import javax.servlet.http.HttpServletResponse;
25  
26  import java.util.HashMap;
27  /**
28   * An abstract Action class that all Join action classes must extend. This
29   * class implements Struts execute() method as a wrapper to a new doExecute()
30   * abstract method. This wrapper is intended to perform some pre-processing
31   * (such as retrieving the specified operation to invoke) and some post-processing
32   * (such as performing different rendering based on given informations).
33   * <br/><br/>
34   * As a consequence, the doExecute() method of the subclasses should only
35   * return <code>ActionForward</code> those path are a page fragment : this
36   * fragment (or tile) will be inserted into a specific page layout by this
37   * super class.
38   * @author  <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
39   * @version $Revision: 1.6 $
40   */
41  public abstract class JoinAction extends Action{
42  
43     // Static -------------------------------------------------------------------
44     
45     /** The key of the ResourceBundle for GUI related resources. */
46     public static final String GUI_KEY = "gui";
47  
48     /** The request parameter which contains the operation name. */
49     public static final String OP_PARAMETER = "op";
50     /** The request parameter which contains graphical rendering operation. */
51     public static final String REND_PARAMETER = "rd";
52     /** The request parameter which tells that request has been made using XmlHttpRequest (Ajax) */
53     public static final String XHR_PARAMETER = "xhr";
54  
55     /** The request attribute which will contain the path of the page body. */
56     public static final String BODY_ATTRIBUTE = "body.path";
57     /** The request parameter which will contain the pathc of the page body. */
58     public static final String  BODY_PARAMETER = "body";
59     /** The request attribute which will contain exception thrown by action processing. */
60     public static final String EXCEPTION_KEY = "exception";
61  
62     /** Rendering value for main page rendering */
63     public static final String REND_MAIN = "main";
64     /** Rendering value for popup page rendering */
65     public static final String REND_POPUP = "popup";
66     /** Rendering value for no page rendering (inclusion necessary) */
67     public static final String REND_NONE = "none";
68  
69  
70     // Attributes ---------------------------------------------------------------
71     
72     /** HashMap used as a cache for ActionForwards. */
73     private HashMap forwardMap = new HashMap();
74     
75     
76     // Abstract -----------------------------------------------------------------
77     
78     /**
79      * Abstract method that subclasses must implement. The real execution must
80      * be done here according to the specified <b>operation</b>. ActionForward
81      * returned by execution should only point on page fragment : this superclass
82      * is responsible of including them within a whole page.
83      * @param operation String representing the operation to invoke on Action
84      * @param mapping Mapping between forwards name and path for this action
85      * @param form The form object containing request parameters
86      * @param request The servlet container request wrapper
87      * @param response The servlet container response wrapper
88      * @return A forward to the next view to render and display
89      * @throws Exception such as InfraStructureExceptions ...
90      */
91     public abstract ActionForward doExecute(String operation, ActionMapping mapping, ActionForm form,
92                             HttpServletRequest request, HttpServletResponse response) throws Exception;
93  
94  
95     // Public -------------------------------------------------------------------
96     
97     /**
98      * Check if user tied to the HttpServletRequest is logged
99      * in Join application (ie : has a non empty UserContainer).
100     * @param request The servlet container request wrapper
101     * @return true if current user is logged in, false otherwise
102     */
103    public static boolean isLoggedIn(HttpServletRequest request){
104       UserContainer container = getUserContainer(request);
105       return (container != null && container.getView() != null);
106    }
107 
108    /**
109     * Retrieve the user container for the user tied to the HttpServletRequest.
110     * Creates an empty container if one doesn't exist already.
111     * @param request The servlet container request wrapper
112     * @return A UserContainer for current request' user (this container may have
113     * no {@code UserView} associated if it's not logged in)
114     */
115    public static UserContainer getUserContainer(HttpServletRequest request){
116       HttpSession session = request.getSession();
117       UserContainer container = (UserContainer)session.getAttribute("userContainer");
118       
119       // Create a UserContainer if one doesn't exist already.
120       if (container == null){
121          container = new UserContainer();
122          session.setAttribute("userContainer", container);
123       }
124       return container;
125    }
126 
127 
128    // Protected ----------------------------------------------------------------
129 
130    /**
131     * Remove the obsolete form associated to action ; wether the form
132     * is request or session scoped.
133     * @param mapping Mapping between forwards name and path for this action
134     * @param request The servlet container request wrapper
135     */
136    protected void removeObsoleteForm(ActionMapping mapping, HttpServletRequest request){
137       // Depending on mapping scope, clear request or session attribute.
138       if (mapping.getAttribute() != null){
139          if ("request".equals(mapping.getScope()))
140             request.removeAttribute(mapping.getAttribute());
141          else
142             request.getSession().removeAttribute(mapping.getAttribute());
143       }
144    }
145 
146    /**
147     * Tells wether a request has been submitted using XmlHttpRequest
148     * @param request The servlet container request wrapper
149     * @return Wether request has been submitted using XmlHttpRequest
150     */
151    protected boolean isXhrRequest(HttpServletRequest request){
152       String xhrAttribute = request.getParameter(XHR_PARAMETER);
153       if (Boolean.valueOf(xhrAttribute).booleanValue())
154          return true;
155       return false;
156    }
157 
158 
159    // Private ------------------------------------------------------------------
160    
161    /**
162     * Retrieve a cached ActionForward using it's path information.
163     * @param path Path corresponding to the ActionForward to get.
164     * @return The corresponding ActionForward
165     */
166    private ActionForward getActionForwardByPath(String path){
167       ActionForward forward = null;
168       // Check cache map first.
169       forward = (ActionForward)forwardMap.get(path);
170       // If null, create it and put it in cache.
171       if (forward == null){
172          forward = new ActionForward();
173          forward.setPath(path);
174          forwardMap.put(path, forward);
175       }
176       // Return forward.
177       return forward;
178    }
179     
180    
181    // Override of Action -------------------------------------------------------
182    
183    /**
184     * This method acts as a wrapper around doExecute() abstract method. First,
185     * it retrieves operation to invoke onto Action (if any). Then, it calls 
186     * doExecute() passing around this operation. Lastly, it uses provided
187     * rendering information to forward the doExecute() result to the correct
188     * page layout (full page, popup, etc ...)
189     * @param mapping Mapping between forwards name and path for this action
190     * @param form The form object containing request parameters
191     * @param request The servlet container request wrapper
192     * @param response The servlet container response wrapper
193     * @return A forward to the next view to render and display
194     * @throws Exception ... this should not happen ...
195     */
196    public ActionForward execute(ActionMapping mapping, ActionForm form,
197                            HttpServletRequest request, HttpServletResponse response) throws Exception{
198 
199       // Retrieve requested operation.
200       String operation = request.getParameter(OP_PARAMETER);
201       // Call doExecute from subclass.
202       ActionForward forward = null;
203       try {forward = doExecute(operation, mapping, form, request, response);}
204       catch (Throwable t){
205          // Store exception within request and forward to error page.
206          request.setAttribute(EXCEPTION_KEY, t);
207          forward = getActionForwardByPath("/jsp/servicefailure.jsp");
208       }
209 
210       // Save next path into request attribute.
211       String fwdPath = ((forward != null) ? forward.getPath() : "");
212       request.setAttribute(BODY_ATTRIBUTE, fwdPath);
213      
214       // Compute the following page path.
215       String nextPagePath = null;
216       if (fwdPath.toLowerCase().indexOf("/action/") > -1){
217          nextPagePath = fwdPath;
218       }
219       else{
220          // Care about rendering info.
221          String rendering = request.getParameter(REND_PARAMETER);
222          if (REND_NONE.equals(rendering) || (isXhrRequest(request) && rendering == null))
223             return forward;
224          else if (REND_POPUP.equals(rendering))
225             nextPagePath = "/pages/popuppage.jsp";
226          else
227             nextPagePath = "/pages/mainpage.jsp";
228       }
229      
230       // Return a cached ActionForward corresponding to page path.
231       ActionForward realForward = getActionForwardByPath(nextPagePath);
232       return realForward;
233    } 
234 }