001: /**********************************************************************************
002: * $URL:https://source.sakaiproject.org/svn/osp/trunk/common/tool-lib/src/java/org/theospi/portfolio/shared/control/servlet/HelperAwareJsfTool.java $
003: * $Id:HelperAwareJsfTool.java 9134 2006-05-08 20:28:42Z chmaurer@iupui.edu $
004: ***********************************************************************************
005: *
006: * Copyright (c) 2005, 2006 The Sakai Foundation.
007: *
008: * Licensed under the Educational Community License, Version 1.0 (the "License");
009: * you may not use this file except in compliance with the License.
010: * You may obtain a copy of the License at
011: *
012: * http://www.opensource.org/licenses/ecl1.php
013: *
014: * Unless required by applicable law or agreed to in writing, software
015: * distributed under the License is distributed on an "AS IS" BASIS,
016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: * See the License for the specific language governing permissions and
018: * limitations under the License.
019: *
020: **********************************************************************************/package org.theospi.portfolio.shared.control.servlet;
021:
022: import org.sakaiproject.jsf.util.JsfTool;
023: import org.sakaiproject.tool.api.ActiveTool;
024: import org.sakaiproject.tool.api.Tool;
025: import org.sakaiproject.tool.api.ToolException;
026: import org.sakaiproject.tool.api.ToolSession;
027: import org.sakaiproject.tool.cover.ActiveToolManager;
028: import org.sakaiproject.tool.cover.SessionManager;
029: import org.sakaiproject.util.Web;
030: import org.sakaiproject.metaobj.shared.control.ToolFinishedView;
031:
032: import javax.servlet.RequestDispatcher;
033: import javax.servlet.ServletException;
034: import javax.servlet.http.HttpServletRequest;
035: import javax.servlet.http.HttpServletResponse;
036: import java.io.IOException;
037: import java.util.Enumeration;
038:
039: /**
040: * Created by IntelliJ IDEA.
041: * User: John Ellis
042: * Date: Nov 11, 2005
043: * Time: 4:17:18 PM
044: * To change this template use File | Settings | File Templates.
045: */
046: public class HelperAwareJsfTool extends JsfTool {
047:
048: private static final String HELPER_EXT = ".helper";
049:
050: private static final String HELPER_SESSION_PREFIX = "session.";
051:
052: protected void dispatch(HttpServletRequest req,
053: HttpServletResponse res) throws ServletException,
054: IOException {
055: // NOTE: this is a simple path dispatching, taking the path as the view id = jsp file name for the view,
056: // with default used if no path and a path prefix as configured.
057: // TODO: need to allow other sorts of dispatching, such as pulling out drill-down ids and making them
058: // available to the JSF
059:
060: // build up the target that will be dispatched to
061: String target = req.getPathInfo();
062:
063: // see if we have a helper request
064: if (sendToHelper(req, res, target)) {
065: return;
066: }
067:
068: // see if we have a resource request - i.e. a path with an extension, and one that is not the JSF_EXT
069: if (isResourceRequest(target)) {
070: // get a dispatcher to the path
071: RequestDispatcher resourceDispatcher = getServletContext()
072: .getRequestDispatcher(target);
073: if (resourceDispatcher != null) {
074: resourceDispatcher.forward(req, res);
075: return;
076: }
077: }
078:
079: if ("Title".equals(req.getParameter("panel"))) {
080: // This allows only one Title JSF for each tool
081: target = "/title.jsf";
082: }
083:
084: else {
085: ToolSession session = SessionManager
086: .getCurrentToolSession();
087:
088: if (target == null || "/".equals(target)
089: || target.length() == 0) {
090: if (!m_defaultToLastView) {
091: // make sure tool session is clean
092: session.clearAttributes();
093: }
094:
095: target = computeDefaultTarget();
096:
097: // make sure it's a valid path
098: if (!target.startsWith("/")) {
099: target = "/" + target;
100: }
101:
102: // now that we've messed with the URL, send a redirect to make it official
103: res.sendRedirect(Web.returnUrl(req, target));
104: return;
105: }
106:
107: // see if we want to change the specifically requested view
108: String newTarget = redirectRequestedTarget(target);
109:
110: // make sure it's a valid path
111: if (!newTarget.startsWith("/")) {
112: newTarget = "/" + newTarget;
113: }
114:
115: if (!newTarget.equals(target)) {
116: // now that we've messed with the URL, send a redirect to make it official
117: res.sendRedirect(Web.returnUrl(req, newTarget));
118: return;
119: }
120: target = newTarget;
121:
122: // store this
123: session.setAttribute(LAST_VIEW_VISITED, target);
124: }
125:
126: // add the configured folder root and extension (if missing)
127: target = m_path + target;
128:
129: // add the default JSF extension (if we have no extension)
130: int lastSlash = target.lastIndexOf("/");
131: int lastDot = target.lastIndexOf(".");
132: if (lastDot < 0 || lastDot < lastSlash) {
133: target += JSF_EXT;
134: }
135:
136: // set the information that can be removed from return URLs
137: req.setAttribute(URL_PATH, m_path);
138: req.setAttribute(URL_EXT, ".jsp");
139:
140: // set the sakai request object wrappers to provide the native, not Sakai set up, URL information
141: // - this assures that the FacesServlet can dispatch to the proper view based on the path info
142: req.setAttribute(Tool.NATIVE_URL, Tool.NATIVE_URL);
143:
144: // TODO: Should setting the HTTP headers be moved up to the portal level as well?
145: res.setContentType("text/html; charset=UTF-8");
146: res.addDateHeader("Expires", System.currentTimeMillis()
147: - (1000L * 60L * 60L * 24L * 365L));
148: res.addDateHeader("Last-Modified", System.currentTimeMillis());
149: res
150: .addHeader("Cache-Control",
151: "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
152: res.addHeader("Pragma", "no-cache");
153:
154: // dispatch to the target
155: /*M_log.debug("dispatching path: " + req.getPathInfo() + " to: " + target + " context: "
156: + getServletContext().getServletContextName());*/
157: RequestDispatcher dispatcher = getServletContext()
158: .getRequestDispatcher(target);
159: dispatcher.forward(req, res);
160:
161: // restore the request object
162: req.removeAttribute(Tool.NATIVE_URL);
163: req.removeAttribute(URL_PATH);
164: req.removeAttribute(URL_EXT);
165: }
166:
167: protected boolean sendToHelper(HttpServletRequest req,
168: HttpServletResponse res, String target) {
169: String path = req.getPathInfo();
170: if (path == null)
171: path = "/";
172:
173: // 0 parts means the path was just "/", otherwise parts[0] = "", parts[1] = item id, parts[2] if present is "edit"...
174: String[] parts = path.split("/");
175:
176: if (parts.length < 2) {
177: return false;
178: }
179:
180: if (!parts[1].endsWith(HELPER_EXT)) {
181: return false;
182: }
183:
184: ToolSession toolSession = SessionManager
185: .getCurrentToolSession();
186:
187: Enumeration params = req.getParameterNames();
188: while (params.hasMoreElements()) {
189: String paramName = (String) params.nextElement();
190: if (paramName.startsWith(HELPER_SESSION_PREFIX)) {
191: String attributeName = paramName
192: .substring(HELPER_SESSION_PREFIX.length());
193: toolSession.setAttribute(attributeName, req
194: .getParameter(paramName));
195: }
196: }
197:
198: // calc helper id
199: int posEnd = parts[1].lastIndexOf(".");
200:
201: String helperId = target.substring(1, posEnd + 1);
202: ActiveTool helperTool = ActiveToolManager
203: .getActiveTool(helperId);
204:
205: //get the current location (if one doesn't exist) and save it for when we return from the helper
206: if (toolSession.getAttribute(helperTool.getId()
207: + Tool.HELPER_DONE_URL) == null) {
208: toolSession
209: .setAttribute(helperTool.getId()
210: + Tool.HELPER_DONE_URL, req
211: .getContextPath()
212: + req.getServletPath()
213: + computeDefaultTarget(true));
214: }
215: toolSession.setAttribute(helperTool.getId() + "thetoolPath",
216: req.getContextPath() + req.getServletPath());
217:
218: // saves the alternate done url map into a tool specific attribute
219: if (toolSession.getAttribute(helperTool.getId()
220: + ToolFinishedView.ALTERNATE_DONE_URL) == null) {
221: toolSession.setAttribute(helperTool.getId()
222: + ToolFinishedView.ALTERNATE_DONE_URL, toolSession
223: .getAttribute(ToolFinishedView.ALTERNATE_DONE_URL));
224: toolSession
225: .setAttribute(
226: helperTool.getId()
227: + ToolFinishedView.ALTERNATE_DONE_URL_MAP,
228: toolSession
229: .getAttribute(ToolFinishedView.ALTERNATE_DONE_URL_MAP));
230: toolSession
231: .removeAttribute(ToolFinishedView.ALTERNATE_DONE_URL);
232: toolSession
233: .removeAttribute(ToolFinishedView.ALTERNATE_DONE_URL_MAP);
234: }
235:
236: /*comment out for using the global parameter rather than tool-by-tool setting
237: SessionState state = UsageSessionService.getSessionState(toolSession.getPlacementId());
238: boolean show_other_sites = ServerConfigurationService.getBoolean("syllabus.resources.show_all_collections.helper", true);
239: state.setAttribute("resources.allow_user_to_see_all_sites", (new Boolean(show_other_sites)).toString());
240: state.setAttribute("resources.user_chooses_to_see_other_sites", (new Boolean(show_other_sites)).toString());
241: */
242: String context = req.getContextPath() + req.getServletPath()
243: + Web.makePath(parts, 1, 2);
244: String toolPath = Web.makePath(parts, 2, parts.length);
245: try {
246: helperTool.help(req, res, context, toolPath);
247: } catch (ToolException e) {
248: throw new RuntimeException(e);
249: }
250:
251: return true; // was handled as helper call
252: }
253:
254: protected String computeDefaultTarget(boolean lastVisited) {
255: // setup for the default view as configured
256: String target = "/" + m_default;
257:
258: // if we are doing lastVisit and there's a last-visited view, for this tool placement / user, use that
259: if (lastVisited) {
260: ToolSession session = SessionManager
261: .getCurrentToolSession();
262: String last = (String) session
263: .getAttribute(LAST_VIEW_VISITED);
264: if (last != null) {
265: target = last;
266: }
267: }
268:
269: return target;
270: }
271: }
|