/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/portal/trunk/portal-tool/tool/src/java/org/sakaiproject/portal/tool/ToolPortal.java $ * $Id: ToolPortal.java 132744 2013-12-18 15:34:44Z ottenhoff@longsight.com $ *********************************************************************************** * * Copyright (c) 2006, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community 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.opensource.org/licenses/ECL-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.sakaiproject.portal.tool; import java.io.IOException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.portal.util.ErrorReporter; import org.sakaiproject.portal.util.ToolURLManagerImpl; import org.sakaiproject.portal.util.URLUtils; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.ToolConfiguration; import org.sakaiproject.site.cover.SiteService; import org.sakaiproject.tool.api.ActiveTool; import org.sakaiproject.tool.api.Placement; import org.sakaiproject.tool.api.Session; import org.sakaiproject.tool.api.Tool; import org.sakaiproject.tool.api.ToolException; import org.sakaiproject.tool.api.ToolSession; import org.sakaiproject.tool.api.ToolURL; import org.sakaiproject.tool.cover.ActiveToolManager; import org.sakaiproject.tool.cover.SessionManager; import org.sakaiproject.util.StringUtil; import org.sakaiproject.util.Web; /** * @author ieb * @since Sakai 2.4 * @version $Rev: 132744 $ */ public class ToolPortal extends HttpServlet { /** Our log (commons). */ private static Log M_log = LogFactory.getLog(ToolPortal.class); /** * Access the Servlet's information display. * * @return servlet information. */ @Override public String getServletInfo() { return "Sakai Tool Portal"; } /** * Initialize the servlet. * * @param config * The servlet config. * @throws ServletException */ @Override public void init(ServletConfig config) throws ServletException { super.init(config); M_log.info("init()"); } /** * Shutdown the servlet. */ @Override public void destroy() { M_log.info("destroy()"); super.destroy(); } /** * Respond to navigation / access requests. * * @param req * The servlet request. * @param res * The servlet response. * @throws ServletException. * @throws IOException. */ @Override protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { try { // get the Sakai session Session session = SessionManager.getCurrentSession(); // our path is /placement-id/tool-destination, but we want to // include anchors and parameters in the destination... String path = URLUtils.getSafePathInfo(req); if ((path == null) || (path.length() <= 1)) { res.sendError(HttpServletResponse.SC_NOT_FOUND); return; } // get the placement id, ignoring the first "/" String[] parts = StringUtil.splitFirst(path.substring(1), "/"); String placementId = parts[0]; // get the toolPath if specified String toolPath = null; if (parts.length == 2) toolPath = "/" + parts[1]; boolean success = doTool(req, res, session, placementId, req.getContextPath() + req.getServletPath() + "/" + placementId, toolPath); } catch (Exception t) { doError(req, res, t); } } /** * Process a tool request * * @param req * @param res * @param session * @param placementId * @param toolContextPath * @param toolPathInfo * @return true if the processing was successful, false if nt * @throws ToolException * @throws IOException */ protected boolean doTool(HttpServletRequest req, HttpServletResponse res, Session session, String placementId, String toolContextPath, String toolPathInfo) throws ToolException, IOException { // find the tool from some site // TODO: all placements are from sites? -ggolden ToolConfiguration siteTool = SiteService.findTool(placementId); if (siteTool == null) return false; // find the tool registered for this ActiveTool tool = ActiveToolManager.getActiveTool(siteTool.getToolId()); if (tool == null) return false; // permission check - visit the site (unless the tool is configured to // bypass) if (tool.getAccessSecurity() == Tool.AccessSecurity.PORTAL) { Site site = null; try { site = SiteService.getSiteVisit(siteTool.getSiteId()); } catch (IdUnusedException e) { return false; } catch (PermissionException e) { // TODO: login here? return false; } } // if the path is not set, and we are expecting one, we need to compute // the path and redirect // we expect a path only if the tool has a registered home -ggolden if ((toolPathInfo == null) && (tool.getHome() != null)) { // what path? The one last visited, or home ToolSession toolSession = SessionManager.getCurrentSession().getToolSession( placementId); String redirectPath = (String) toolSession .getAttribute(ActiveTool.TOOL_ATTR_CURRENT_DESTINATION); if (redirectPath == null) { redirectPath = tool.getHome(); } // redirect with this tool path String redirectUrl = ServerConfigurationService.getServerUrl() + toolContextPath + redirectPath; res.sendRedirect(res.encodeRedirectURL(redirectUrl)); return true; } // store the path as the current path, if we are doing this if (tool.getHome() != null) { ToolSession toolSession = SessionManager.getCurrentSession().getToolSession( placementId); toolSession.setAttribute(ActiveTool.TOOL_ATTR_CURRENT_DESTINATION, toolPathInfo); } // prepare for the forward setupForward(req, res, siteTool, siteTool.getSkin()); req.setAttribute(ToolURL.MANAGER, new ToolURLManagerImpl(res)); // let the tool do the the work (forward) tool.forward(req, res, siteTool, toolContextPath, toolPathInfo); return true; } protected void doError(HttpServletRequest req, HttpServletResponse res, Throwable t) { ErrorReporter err = new ErrorReporter(); err.report(req, res, t); } /** * Respond to data posting requests. * * @param req * The servlet request. * @param res * The servlet response. * @throws ServletException. * @throws IOException. */ @Override protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { doGet(req, res); } /** * Setup the request attributes with information used by the tools in their * response. * * @param req * @param res * @param p * @param skin * @throws ToolException */ // NOTE: This code is duplicated in SkinnableCharonPortal.java // make sure to change code both places protected void setupForward(HttpServletRequest req, HttpServletResponse res, Placement p, String skin) throws ToolException { // setup html information that the tool might need (skin, body on load, // js includes, etc). if (skin == null || skin.length() == 0) skin = ServerConfigurationService.getString("skin.default"); String skinRepo = ServerConfigurationService.getString("skin.repo"); String headCssToolBase = "<link href=\"" + skinRepo + "/tool_base.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />\n"; String headCssToolSkin = "<link href=\"" + skinRepo + "/" + skin + "/tool.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />\n"; String headCss = headCssToolBase + headCssToolSkin; String headJs = "<script type=\"text/javascript\" src=\"/library/js/headscripts.js\"></script>\n"; String head = headCss + headJs; StringBuilder bodyonload = new StringBuilder(); if (p != null) { String element = Web.escapeJavascript("Main" + p.getId()); bodyonload.append("setMainFrameHeight('" + element + "');"); } bodyonload.append("setFocus(focus_path);"); req.setAttribute("sakai.html.head", head); req.setAttribute("sakai.html.head.css", headCss); req.setAttribute("sakai.html.head.css.base", headCssToolBase); req.setAttribute("sakai.html.head.css.skin", headCssToolSkin); req.setAttribute("sakai.html.head.js", headJs); req.setAttribute("sakai.html.body.onload", bodyonload.toString()); } }