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
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
71
72 /** HashMap used as a cache for ActionForwards. */
73 private HashMap forwardMap = new HashMap();
74
75
76
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
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
120 if (container == null){
121 container = new UserContainer();
122 session.setAttribute("userContainer", container);
123 }
124 return container;
125 }
126
127
128
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
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
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
169 forward = (ActionForward)forwardMap.get(path);
170
171 if (forward == null){
172 forward = new ActionForward();
173 forward.setPath(path);
174 forwardMap.put(path, forward);
175 }
176
177 return forward;
178 }
179
180
181
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
200 String operation = request.getParameter(OP_PARAMETER);
201
202 ActionForward forward = null;
203 try {forward = doExecute(operation, mapping, form, request, response);}
204 catch (Throwable t){
205
206 request.setAttribute(EXCEPTION_KEY, t);
207 forward = getActionForwardByPath("/jsp/servicefailure.jsp");
208 }
209
210
211 String fwdPath = ((forward != null) ? forward.getPath() : "");
212 request.setAttribute(BODY_ATTRIBUTE, fwdPath);
213
214
215 String nextPagePath = null;
216 if (fwdPath.toLowerCase().indexOf("/action/") > -1){
217 nextPagePath = fwdPath;
218 }
219 else{
220
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
231 ActionForward realForward = getActionForwardByPath(nextPagePath);
232 return realForward;
233 }
234 }