/********************************************************************************** * $URL: https://source.sakaiproject.org/svn/tags/sakai_2-1-1/portal/charon/src/java/org/sakaiproject/portal/charon/CharonPortal.java $ * $Id: CharonPortal.java 4046 2005-11-21 13:20:38Z lance@indiana.edu $ ********************************************************************************** * * Copyright (c) 2005 The Regents of the University of Michigan, Trustees of Indiana University, * Board of Trustees of the Leland Stanford, Jr., University, and The MIT Corporation * * Licensed under the Educational Community License Version 1.0 (the "License"); * By obtaining, using and/or copying this Original Work, you agree that you have read, * understand, and will comply with the terms and conditions of the Educational Community License. * You may obtain a copy of the License at: * * http://cvs.sakaiproject.org/licenses/license_1_0.html * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE * AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * **********************************************************************************/ package org.sakaiproject.portal.charon; import java.io.IOException; import java.io.PrintWriter; import java.text.DateFormat; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.ResourceBundle; import java.util.Vector; 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.api.kernel.session.Session; import org.sakaiproject.api.kernel.session.ToolSession; import org.sakaiproject.api.kernel.session.cover.SessionManager; import org.sakaiproject.api.kernel.thread_local.cover.ThreadLocalManager; import org.sakaiproject.api.kernel.tool.ActiveTool; import org.sakaiproject.api.kernel.tool.Placement; import org.sakaiproject.api.kernel.tool.Tool; import org.sakaiproject.api.kernel.tool.ToolURL; import org.sakaiproject.api.kernel.tool.cover.ActiveToolManager; import org.sakaiproject.api.kernel.tool.cover.ToolManager; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.portal.charon.ToolURLManagerImpl; import org.sakaiproject.service.framework.config.cover.ServerConfigurationService; import org.sakaiproject.service.legacy.authzGroup.Role; import org.sakaiproject.service.legacy.entity.ResourceProperties; import org.sakaiproject.service.legacy.preference.Preferences; import org.sakaiproject.service.legacy.preference.cover.PreferencesService; import org.sakaiproject.service.legacy.security.cover.SecurityService; import org.sakaiproject.service.legacy.site.Site; import org.sakaiproject.service.legacy.site.SitePage; import org.sakaiproject.service.legacy.site.ToolConfiguration; import org.sakaiproject.service.legacy.site.cover.SiteService; import org.sakaiproject.util.java.StringUtil; import org.sakaiproject.util.web.Web; /** *

* Charon is the Sakai Site based portal. *

* * @author University of Michigan, Sakai Software Development Team * @version $Revision: 4046 $ */ public class CharonPortal extends HttpServlet { /** Our log (commons). */ private static Log M_log = LogFactory.getLog(CharonPortal.class); /** messages. */ private static ResourceBundle rb = ResourceBundle.getBundle("sitenav"); /** Session attribute root for storing a site's last page visited - just append the site id. */ protected static final String ATTR_SITE_PAGE = "sakai.portal.site."; /** ThreadLocal attribute set while we are processing an error. */ protected static final String ATTR_ERROR = "org.sakaiproject.portal.error"; /** Error response modes. */ protected static final int ERROR_SITE = 0; protected static final int ERROR_GALLERY = 1; protected static final int ERROR_WORKSITE = 2; /** Names of tool config/registration attributes that control the rendering of the tool's titlebar */ private static final String TOOLCONFIG_SHOW_RESET_BUTTON = "reset.button"; private static final String TOOLCONFIG_SHOW_HELP_BUTTON = "help.button"; private static final String TOOLCONFIG_HELP_DOCUMENT_ID = "help.id"; private static final String TOOLCONFIG_HELP_DOCUMENT_URL = "help.url"; /** * Shutdown the servlet. */ public void destroy() { M_log.info("destroy()"); super.destroy(); } protected void doError(HttpServletRequest req, HttpServletResponse res, Session session, int mode) throws IOException { if (ThreadLocalManager.get(ATTR_ERROR) == null) { ThreadLocalManager.set(ATTR_ERROR, ATTR_ERROR); // send to the error site switch (mode) { case ERROR_SITE: { doSite(req, res, session, "!error", null, req.getContextPath() + req.getServletPath()); break; } case ERROR_GALLERY: { doGallery(req, res, session, "!error", null, req.getContextPath() + req.getServletPath()); break; } case ERROR_WORKSITE: { doWorksite(req, res, session, "!error", null, req.getContextPath() + req.getServletPath()); break; } } return; } // error and we cannot use the error site... // form a context sensitive title String title = ServerConfigurationService.getString("ui.service") + " : Portal"; // start the response PrintWriter out = startResponse(res, title, null); // Show session information out.println("

Session

"); showSession(out, true); out.println("

Unknown Request

"); Web.snoop(out, true, getServletConfig(), req); // end the response endResponse(out); } protected void doGallery(HttpServletRequest req, HttpServletResponse res, Session session, String siteId, String pageId, String toolContextPath) throws IOException { // check to default site id if (siteId == null) { if (session.getUserId() == null) { siteId = ServerConfigurationService.getGatewaySiteId(); } else { siteId = SiteService.getUserSiteId(session.getUserId()); } } // if no page id, see if there was a last page visited for this site if (pageId == null) { pageId = (String) session.getAttribute(ATTR_SITE_PAGE + siteId); } // find the site, for visiting Site site = null; try { site = SiteService.getSiteVisit(siteId); } catch (IdUnusedException e) { doError(req, res, session, ERROR_GALLERY); return; } catch (PermissionException e) { // if not logged in, give them a chance if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); } else { doError(req, res, session, ERROR_GALLERY); } return; } // find the page, or use the first page if pageId not found SitePage page = site.getPage(pageId); if (page == null) { List pages = site.getPages(); if (!pages.isEmpty()) { page = (SitePage) site.getPages().get(0); } } if (page == null) { doError(req, res, session, ERROR_GALLERY); return; } // store the last page visited session.setAttribute(ATTR_SITE_PAGE + siteId, page.getId()); // form a context sensitive title String title = ServerConfigurationService.getString("ui.service") + " : " + site.getTitle() + " : " + page.getTitle(); // start the response PrintWriter out = startResponse(res, title, site.getSkin()); // the 'little' top area includeGalleryNav(out, req, session, siteId); String siteType = calcSiteType(siteId); out.println("
"); includeWorksite(out, req, session, site, page, toolContextPath, "gallery"); out.println("
"); includeBottom(out); // end the response endResponse(out); } protected void doGalleryTabs(HttpServletRequest req, HttpServletResponse res, Session session, String siteId) throws IOException { String skin = SiteService.getSiteSkin(siteId); // start the response PrintWriter out = startResponse(res, "Site Navigation", skin); includeTabs(out, req, session, siteId, "gallery", true); // end the response endResponse(out); } /** * Respond to navigation / access requests. * * @param req * The servlet request. * @param res * The servlet response. * @throws ServletException. * @throws IOException. */ protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // get the Sakai session Session session = SessionManager.getCurrentSession(); // recognize what to do from the path String option = req.getPathInfo(); // if missing, set it to home or gateway if ((option == null) || ("/".equals(option))) { if (session.getUserId() == null) { option = "/site/" + ServerConfigurationService.getGatewaySiteId(); } else { option = "/site/" + SiteService.getUserSiteId(session.getUserId()); } } // get the parts (the first will be "") String[] parts = option.split("/"); // recognize and dispatch the 'tool' option: [1] = "tool", [2] = placement id (of a site's tool placement), rest for the tool if ((parts.length >= 2) && (parts[1].equals("tool"))) { doTool(req, res, session, parts[2], req.getContextPath() + req.getServletPath() + Web.makePath(parts, 1, 3), Web .makePath(parts, 3, parts.length)); } else if ((parts.length >= 2) && (parts[1].equals("title"))) { doTitle(req, res, session, parts[2], req.getContextPath() + req.getServletPath() + Web.makePath(parts, 1, 3), Web .makePath(parts, 3, parts.length)); } // recognize a dispatch the 'page' option (tools on a page) else if ((parts.length == 3) && (parts[1].equals("page"))) { doPage(req, res, session, parts[2], req.getContextPath() + req.getServletPath()); } // recognize a dispatch the 'worksite' option (pages navigation + tools on a page) else if ((parts.length >= 3) && (parts[1].equals("worksite"))) { // recognize an optional page/pageid String pageId = null; if ((parts.length == 5) && (parts[3].equals("page"))) { pageId = parts[4]; } doWorksite(req, res, session, parts[2], pageId, req.getContextPath() + req.getServletPath()); } // recognize a dispatch the 'gallery' option (site tabs + pages navigation + tools on a page) else if ((parts.length >= 2) && (parts[1].equals("gallery"))) { // recognize an optional page/pageid String pageId = null; if ((parts.length == 5) && (parts[3].equals("page"))) { pageId = parts[4]; } // site might be specified String siteId = null; if (parts.length >= 3) { siteId = parts[2]; } doGallery(req, res, session, siteId, pageId, req.getContextPath() + req.getServletPath()); } // recognize a dispatch the 'site' option (site logo and tabs + pages navigation + tools on a page) else if ((parts.length >= 2) && (parts[1].equals("site"))) { // recognize an optional page/pageid String pageId = null; if ((parts.length == 5) && (parts[3].equals("page"))) { pageId = parts[4]; } // site might be specified String siteId = null; if (parts.length >= 3) { siteId = parts[2]; } doSite(req, res, session, siteId, pageId, req.getContextPath() + req.getServletPath()); } // recognize site tabs else if ((parts.length == 3) && (parts[1].equals("site_tabs"))) { doSiteTabs(req, res, session, parts[2]); } // recognize gallery tabs else if ((parts.length == 3) && (parts[1].equals("gallery_tabs"))) { doGalleryTabs(req, res, session, parts[2]); } // recognize nav login else if ((parts.length == 3) && (parts[1].equals("nav_login"))) { doNavLogin(req, res, session, parts[2]); } // recognize nav login for the gallery else if ((parts.length == 3) && (parts[1].equals("nav_login_gallery"))) { doNavLoginGallery(req, res, session, parts[2]); } // recognize presence else if ((parts.length >= 3) && (parts[1].equals("presence"))) { doPresence(req, res, session, parts[2], req.getContextPath() + req.getServletPath() + Web.makePath(parts, 1, 3), Web .makePath(parts, 3, parts.length)); } // recognize help else if ((parts.length >= 2) && (parts[1].equals("help"))) { doHelp(req, res, session, req.getContextPath() + req.getServletPath() + Web.makePath(parts, 1, 2), Web.makePath(parts, 2, parts.length)); } // recognize and dispatch the 'login' option else if ((parts.length == 2) && (parts[1].equals("login"))) { doLogin(req, res, session, null, false); } // recognize and dispatch the 'login' options else if ((parts.length == 2) && ((parts[1].equals("xlogin")))) { doLogin(req, res, session, null, true); } // recognize and dispatch the 'login' option for gallery else if ((parts.length == 2) && (parts[1].equals("login_gallery"))) { doLogin(req, res, session, "/gallery", false); } // recognize and dispatch the 'logout' option else if ((parts.length == 2) && (parts[1].equals("logout"))) { doLogout(req, res, session, null); } // recognize and dispatch the 'logout' option for gallery else if ((parts.length == 2) && (parts[1].equals("logout_gallery"))) { doLogout(req, res, session, "/gallery"); } // handle an unrecognized request else { doError(req, res, session, ERROR_SITE); } } protected void doTitle(HttpServletRequest req, HttpServletResponse res, Session session, String placementId, String toolContextPath, String toolPathInfo) throws IOException { // find the tool from some site ToolConfiguration siteTool = SiteService.findTool(placementId); if (siteTool == null) { doError(req, res, session, ERROR_WORKSITE); return; } // find the tool registered for this ActiveTool tool = ActiveToolManager.getActiveTool(siteTool.getTool().getId()); if (tool == null) { doError(req, res, session, ERROR_WORKSITE); return; } // don't check permissions when just displaying the title... // // 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) // { // doError(req, res, session, ERROR_WORKSITE); // return; // } // catch (PermissionException e) // { // // if not logged in, give them a chance // if (session.getUserId() == null) // { // doLogin(req, res, session, req.getPathInfo(), false); // } // else // { // doError(req, res, session, ERROR_WORKSITE); // } // return; // } // } includeTitle(tool, req, res, siteTool, siteTool.getSkin(), toolContextPath, toolPathInfo); } /** * Output the content of the title frame for a tool. */ protected void includeTitle(ActiveTool tool, HttpServletRequest req, HttpServletResponse res, ToolConfiguration placement, String skin, String toolContextPath, String toolPathInfo) throws IOException { res.setContentType("text/html; charset=UTF-8"); res.addDateHeader("Expires", System.currentTimeMillis() - (1000L * 60L * 60L * 24L * 365L)); res.addDateHeader("Last-Modified", System.currentTimeMillis()); res.addHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"); res.addHeader("Pragma", "no-cache"); if (skin == null || skin.length() == 0) skin = ServerConfigurationService.getString("skin.default"); String skinRepo = ServerConfigurationService.getString("skin.repo"); // the title to display in the title frame String toolTitle = Web.escapeHtml(placement.getTitle()); // for the reset button String resetActionUrl = toolContextPath+"?reset=true"; boolean resetToolNow = "true".equals(req.getParameter("reset")); boolean showResetButton = !"false".equals(placement.getConfig().getProperty(TOOLCONFIG_SHOW_RESET_BUTTON)); // for the help button // get the help document ID from the tool config (tool registration usually). // The help document ID defaults to the tool ID boolean helpEnabledGlobally = ServerConfigurationService.getBoolean("helpEnabled", true); boolean helpEnabledInTool = !"false".equals(placement.getConfig().getProperty(TOOLCONFIG_SHOW_HELP_BUTTON)); boolean showHelpButton = helpEnabledGlobally && helpEnabledInTool; String helpActionUrl = ""; if (showHelpButton) { String helpDocId = placement.getConfig().getProperty(TOOLCONFIG_HELP_DOCUMENT_ID); String helpDocUrl = placement.getConfig().getProperty(TOOLCONFIG_HELP_DOCUMENT_URL); if (helpDocUrl != null && helpDocUrl.length() > 0) { helpActionUrl = helpDocUrl; } else { if (helpDocId == null || helpDocId.length() == 0) { helpDocId = tool.getId(); } helpActionUrl = ServerConfigurationService.getHelpUrl(helpDocId); } } PrintWriter out = res.getWriter(); final String headHtml = "\n" + "\n" + " \n" + " \n" + " \n" + " \n" + " \n" + " "+toolTitle+"\n" + " \n" + " \n"; final String tailHtml = "\n"; out.write(headHtml); out.write("\n"); out.write("\n"); out.write("\t\n"); out.write("\t\n"); out.write("\n"); out.write("
\n"); if (showResetButton) { out.write("\t\t\"Reset\"" ); } out.write("

"+toolTitle+"\n"+"\t

\n"); if (showHelpButton) { out.write("\t\t\"Help\"\n"); } out.write("\t
\n"); if (resetToolNow) { // cause main tool frame to be reset // clear the session data associated with the tool - should reset the tool Session s = SessionManager.getCurrentSession(); ToolSession ts = s.getToolSession(placement.getId()); ts.clearAttributes(); // redirect the main tool frame back to the initial tool URL. String mainFrameId = Web.escapeJavascript("Main" + placement.getId()); String mainFrameUrl = Web.returnUrl(req, "/tool/" + Web.escapeUrl(placement.getId())+"?panel=Main"); out.write("\n"); } out.write(tailHtml); } protected void doLogin(HttpServletRequest req, HttpServletResponse res, Session session, String returnPath, boolean skipContainer) throws IOException { // setup for the helper if needed (Note: in session, not tool session, special for Login helper) if (session.getAttribute(Tool.HELPER_DONE_URL) == null) { // where to go after session.setAttribute(Tool.HELPER_DONE_URL, Web.returnUrl(req, returnPath)); } ActiveTool tool = ActiveToolManager.getActiveTool("sakai.login"); // to skip container auth for this one, forcing things to be handled internaly, set the "extreme" login path String loginPath = (skipContainer ? "/xlogin" : "/login"); String context = req.getContextPath() + req.getServletPath() + loginPath; tool.help(req, res, context, loginPath); } protected void doLogout(HttpServletRequest req, HttpServletResponse res, Session session, String returnPath) throws IOException { // setup for the helper if needed (Note: in session, not tool session, special for Login helper) if (session.getAttribute(Tool.HELPER_DONE_URL) == null) { // where to go after String loggedOutUrl = ServerConfigurationService.getLoggedOutUrl(); session.setAttribute(Tool.HELPER_DONE_URL, loggedOutUrl); } ActiveTool tool = ActiveToolManager.getActiveTool("sakai.login"); String context = req.getContextPath() + req.getServletPath() + "/logout"; tool.help(req, res, context, "/logout"); } protected void doNavLogin(HttpServletRequest req, HttpServletResponse res, Session session, String siteId) throws IOException { // start the response PrintWriter out = startResponse(res, "Login", null); includeLogo(out, req, session, siteId); out.println("

"); // end the response endResponse(out); } protected void doNavLoginGallery(HttpServletRequest req, HttpServletResponse res, Session session, String siteId) throws IOException { // start the response PrintWriter out = startResponse(res, "Login", null); includeGalleryLogin(out, req, session, siteId); out.println("

"); // end the response endResponse(out); } protected void doPage(HttpServletRequest req, HttpServletResponse res, Session session, String pageId, String toolContextPath) throws IOException { // find the page from some site SitePage page = SiteService.findPage(pageId); if (page == null) { doError(req, res, session, ERROR_WORKSITE); return; } // permission check - visit the site Site site = null; try { site = SiteService.getSiteVisit(page.getSiteId()); } catch (IdUnusedException e) { doError(req, res, session, ERROR_WORKSITE); return; } catch (PermissionException e) { // if not logged in, give them a chance if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); } else { doError(req, res, session, ERROR_WORKSITE); } return; } // form a context sensitive title String title = ServerConfigurationService.getString("ui.service") + " : " + site.getTitle() + " : " + page.getTitle(); // start the response PrintWriter out = startResponse(res, title, page.getSkin()); // div to wrap the works String siteType = calcSiteType(site.getId()); out.println("
"); includePage(out, req, page, toolContextPath, "contentFull"); out.println("
"); // end the response endResponse(out); } /** * Respond to data posting requests. * * @param req * The servlet request. * @param res * The servlet response. * @throws ServletException. * @throws IOException. */ protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // get the Sakai session Session session = SessionManager.getCurrentSession(); // recognize what to do from the path String option = req.getPathInfo(); // if missing, we have a stray post if ((option == null) || ("/".equals(option))) { doError(req, res, session, ERROR_SITE); return; } // get the parts (the first will be "") String[] parts = option.split("/"); // recognize and dispatch the 'tool' option: [1] = "tool", [2] = placement id (of a site's tool placement), rest for the tool if ((parts.length >= 2) && (parts[1].equals("tool"))) { doTool(req, res, session, parts[2], req.getContextPath() + req.getServletPath() + Web.makePath(parts, 1, 3), Web .makePath(parts, 3, parts.length)); } else if ((parts.length >= 2) && (parts[1].equals("title"))) { doTitle(req, res, session, parts[2], req.getContextPath() + req.getServletPath() + Web.makePath(parts, 1, 3), Web .makePath(parts, 3, parts.length)); } // recognize and dispatch the 'login' options else if ((parts.length == 2) && ((parts[1].equals("login") || (parts[1].equals("xlogin"))))) { postLogin(req, res, session, parts[1]); } // recognize help else if ((parts.length >= 2) && (parts[1].equals("help"))) { doHelp(req, res, session, req.getContextPath() + req.getServletPath() + Web.makePath(parts, 1, 2), Web.makePath(parts, 2, parts.length)); } // handle an unrecognized request else { doError(req, res, session, ERROR_SITE); } } protected void doPresence(HttpServletRequest req, HttpServletResponse res, Session session, String siteId, String toolContextPath, String toolPathInfo) throws IOException { // permission check - visit the site Site site = null; try { site = SiteService.getSiteVisit(siteId); } catch (IdUnusedException e) { doError(req, res, session, ERROR_WORKSITE); return; } catch (PermissionException e) { // if not logged in, give them a chance if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); } else { doError(req, res, session, ERROR_WORKSITE); } return; } // get the skin for the site String skin = site.getSkin(); // find the tool registered for this ActiveTool tool = ActiveToolManager.getActiveTool("sakai.presence"); if (tool == null) { doError(req, res, session, ERROR_WORKSITE); return; } // form a placement based on the site and the fact that this is that site's presence... // Note: the placement is transient, but will always have the same id and context based on the siteId org.sakaiproject.util.Placement placement = new org.sakaiproject.util.Placement(siteId + "-presence", tool, null, siteId, null); forwardTool(tool, req, res, placement, skin, toolContextPath, toolPathInfo); } protected void doHelp(HttpServletRequest req, HttpServletResponse res, Session session, String toolContextPath, String toolPathInfo) throws IOException { // permission check - none // get the detault skin String skin = ServerConfigurationService.getString("skin.default"); // find the tool registered for this ActiveTool tool = ActiveToolManager.getActiveTool("sakai.help"); if (tool == null) { doError(req, res, session, ERROR_WORKSITE); return; } // form a placement based on ... help TODO: is this enough? // Note: the placement is transient, but will always have the same id and (null) context org.sakaiproject.util.Placement placement = new org.sakaiproject.util.Placement("help", tool, null, null, null); forwardTool(tool, req, res, placement, skin, toolContextPath, toolPathInfo); } protected void doSite(HttpServletRequest req, HttpServletResponse res, Session session, String siteId, String pageId, String toolContextPath) throws IOException { // default site if not set if (siteId == null) { if (session.getUserId() == null) { siteId = ServerConfigurationService.getGatewaySiteId(); } else { siteId = SiteService.getUserSiteId(session.getUserId()); } } // if no page id, see if there was a last page visited for this site if (pageId == null) { pageId = (String) session.getAttribute(ATTR_SITE_PAGE + siteId); } // find the site, for visiting Site site = null; try { site = SiteService.getSiteVisit(siteId); } catch (IdUnusedException e) { doError(req, res, session, ERROR_SITE); return; } catch (PermissionException e) { // if not logged in, give them a chance if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); } else { doError(req, res, session, ERROR_SITE); } return; } // find the page, or use the first page if pageId not found SitePage page = site.getPage(pageId); if (page == null) { List pages = site.getOrderedPages(); if (!pages.isEmpty()) { page = (SitePage) site.getPages().get(0); } } if (page == null) { doError(req, res, session, ERROR_SITE); return; } // store the last page visited session.setAttribute(ATTR_SITE_PAGE + siteId, page.getId()); // form a context sensitive title String title = ServerConfigurationService.getString("ui.service") + " : " + site.getTitle() + " : " + page.getTitle(); // start the response PrintWriter out = startResponse(res, title, site.getSkin()); // the 'full' top area includeSiteNav(out, req, session, siteId); String siteType = calcSiteType(siteId); out.println("
"); includeWorksite(out, req, session, site, page, toolContextPath, "site"); out.println("
"); includeBottom(out); // end the response endResponse(out); } protected void doSiteTabs(HttpServletRequest req, HttpServletResponse res, Session session, String siteId) throws IOException { // get the site's skin String skin = SiteService.getSiteSkin(siteId); // start the response PrintWriter out = startResponse(res, "Site Navigation", skin); includeLogo(out, req, session, siteId); includeTabs(out, req, session, siteId, "site", false); // end the response endResponse(out); } protected void doTool(HttpServletRequest req, HttpServletResponse res, Session session, String placementId, String toolContextPath, String toolPathInfo) throws IOException { // find the tool from some site ToolConfiguration siteTool = SiteService.findTool(placementId); if (siteTool == null) { doError(req, res, session, ERROR_WORKSITE); return; } // find the tool registered for this ActiveTool tool = ActiveToolManager.getActiveTool(siteTool.getTool().getId()); if (tool == null) { doError(req, res, session, ERROR_WORKSITE); return; } // 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) { doError(req, res, session, ERROR_WORKSITE); return; } catch (PermissionException e) { // if not logged in, give them a chance if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); } else { doError(req, res, session, ERROR_WORKSITE); } return; } } forwardTool(tool, req, res, siteTool, siteTool.getSkin(), toolContextPath, toolPathInfo); } /** * Forward to the tool - but first setup JavaScript/CSS etc that the tool will render */ protected void forwardTool(ActiveTool tool, HttpServletRequest req, HttpServletResponse res, Placement p, String skin, String toolContextPath, String toolPathInfo) { // 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 = "\n"; String headCssToolSkin = "\n"; String headCss = headCssToolBase + headCssToolSkin; String headJs = "\n"; String head = headCss + headJs; StringBuffer bodyonload = new StringBuffer(); if (p != null) { String element = Web.escapeJavascript("Main" + p.getId()); bodyonload.append("setMainFrameHeight('" + element + "');"); } bodyonload.append("setFocus(focus_path);"); // to force all non-legacy tools to use the standard css // to help in transition (needs corresponding entry in properties) // if ("true".equals(ServerConfigurationService.getString("skin.force"))) // { // headJs = headJs + headCss; // } 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()); req.setAttribute(ToolURL.MANAGER, new ToolURLManagerImpl(res)); // let the tool do the the work (forward) tool.forward(req, res, p, toolContextPath, toolPathInfo); } protected void doWorksite(HttpServletRequest req, HttpServletResponse res, Session session, String siteId, String pageId, String toolContextPath) throws IOException { // if no page id, see if there was a last page visited for this site if (pageId == null) { pageId = (String) session.getAttribute(ATTR_SITE_PAGE + siteId); } // find the site, for visiting Site site = null; try { site = SiteService.getSiteVisit(siteId); } catch (IdUnusedException e) { doError(req, res, session, ERROR_WORKSITE); return; } catch (PermissionException e) { // if not logged in, give them a chance if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); } else { doError(req, res, session, ERROR_WORKSITE); } return; } // find the page, or use the first page if pageId not found SitePage page = site.getPage(pageId); if (page == null) { List pages = site.getPages(); if (!pages.isEmpty()) { page = (SitePage) site.getPages().get(0); } } if (page == null) { doError(req, res, session, ERROR_WORKSITE); return; } // store the last page visited session.setAttribute(ATTR_SITE_PAGE + siteId, page.getId()); // form a context sensitive title String title = ServerConfigurationService.getString("ui.service") + " : " + site.getTitle() + " : " + page.getTitle(); // start the response PrintWriter out = startResponse(res, title, site.getSkin()); String siteType = calcSiteType(siteId); out.println("
"); includeWorksite(out, req, session, site, page, toolContextPath, "worksite"); out.println("
"); // end the response endResponse(out); } protected void endResponse(PrintWriter out) throws IOException { out.println(""); } protected String getScriptPath() { String libPath = "/library"; return libPath + "/js/"; } /** * Access the Servlet's information display. * * @return servlet information. */ public String getServletInfo() { return "Sakai Charon Portal"; } protected void includeBottom(PrintWriter out) { String copyright = ServerConfigurationService.getString("bottom.copyrighttext"); String service = ServerConfigurationService.getString("ui.service", "Sakai"); String serviceVersion = ServerConfigurationService.getString("version.service", "?"); String sakaiVersion = ServerConfigurationService.getString("version.sakai", "?"); String server = ServerConfigurationService.getServerId(); String[] bottomNav = ServerConfigurationService.getStrings("bottomnav"); String[] poweredByUrl = ServerConfigurationService.getStrings("powered.url"); String[] poweredByImage = ServerConfigurationService.getStrings("powered.img"); String[] poweredByAltText = ServerConfigurationService.getStrings("powered.alt"); out.println("
"); out.println("
"); out.println(" |"); if ((bottomNav != null) && (bottomNav.length > 0)) { for (int i = 0; i < bottomNav.length; i++) { out.println(" " + bottomNav[i] + " | "); } } out.println("
"); out.println("
"); if ((poweredByUrl != null) && (poweredByImage != null) && (poweredByAltText != null) && (poweredByUrl.length == poweredByImage.length) && (poweredByUrl.length == poweredByAltText.length)) { for (int i = 0; i < poweredByUrl.length; i++) { out.println(" " + Web.escapeHtml(rb.getString("site.newwindow")) + " " + "\"""); } } else { out.println(" Opens in a new window " + "\"Powered"); } out.println("
"); out.println(" " + copyright + "
"); out.println(" " + service + " - " + serviceVersion + " - Sakai " + sakaiVersion + " - Server \"" + server + "\"
"); out.println("
"); out.println("
"); out.println("
"); out.println("
"); } protected void includeGalleryLogin(PrintWriter out, HttpServletRequest req, Session session, String siteId) throws IOException { out.println("
"); out.println(""); out.println(" "); out.println(" "); out.println(" "); out.println("
"); this.includeLogin(out, req, session); out.println("
"); } protected void includeGalleryNav(PrintWriter out, HttpServletRequest req, Session session, String siteId) { boolean loggedIn = session.getUserId() != null; boolean topLogin = ServerConfigurationService.getBoolean("top.login", true); String siteNavUrl = null; if (loggedIn) { siteNavUrl = Web.returnUrl(req, "/gallery_tabs/" + Web.escapeUrl(siteId)); } else { siteNavUrl = Web.returnUrl(req, "/nav_login_gallery/" + Web.escapeUrl(siteId)); } // gsilver - jump to links String accessibilityURL = ServerConfigurationService.getString("accessibility.url"); if (accessibilityURL != null && accessibilityURL != "") { out.println("" + Web.escapeHtml(rb.getString("sit.accessibility")) + ""); } out.println("" + Web.escapeHtml(rb.getString("sit.jumpcontent")) + ""); out.println("" + Web.escapeHtml(rb.getString("sit.jumptools")) + ""); out.println("" + Web.escapeHtml(rb.getString("sit.jumpworksite")) + ""); out.println(""); out.println(""); } protected void includeLogo(PrintWriter out, HttpServletRequest req, Session session, String siteId) throws IOException { String skin = SiteService.getSiteSkin(siteId); if (skin == null) { skin = ServerConfigurationService.getString("skin.default"); } String skinRepo = ServerConfigurationService.getString("skin.repo"); String logo = skinRepo + "/" + skin + "/images/logo_inst.gif"; String banner = skinRepo + "/" + skin + "/images/banner_inst.gif"; out.println("
"); out.println(""); out.println(" "); out.println(" "); out.println(" "); out.println(" "); out.println(" "); out.println("
"); out.println(" \"Logo\""); out.println(" "); out.println(" \"Banner\""); out.println(" "); includeLogin(out, req, session); out.println("
"); } protected void includeLogin(PrintWriter out, HttpServletRequest req, Session session) { // for the main login/out link String logInOutUrl = Web.serverUrl(req); String message = null; String image1 = null; // for a possible second link String logInOutUrl2 = null; String message2 = null; String image2 = null; // check for the top.login (where the login fields are present instead of a login link, // but ignore it if container.login is set boolean topLogin = Boolean.TRUE.toString().equalsIgnoreCase(ServerConfigurationService.getString("top.login")); boolean containerLogin = Boolean.TRUE.toString().equalsIgnoreCase(ServerConfigurationService.getString("container.login")); if (containerLogin) topLogin = false; // if not logged in they get login if (session.getUserId() == null) { // we don't need any of this if we are doing top login if (!topLogin) { logInOutUrl += "/portal/login"; message = rb.getString("log.login"); // check for an image for the login image1 = StringUtil.trimToNull(ServerConfigurationService.getString("login.icon")); // check for a possible second, xlogin link if (Boolean.TRUE.toString().equalsIgnoreCase(ServerConfigurationService.getString("xlogin.enabled"))) { message2 = StringUtil.trimToNull(ServerConfigurationService.getString("xlogin.text")); image2 = StringUtil.trimToNull(ServerConfigurationService.getString("xlogin.icon")); logInOutUrl2 = "/portal/xlogin"; } } } // if logged in they get logout else { logInOutUrl += "/portal/logout"; message = rb.getString("sit.log"); // check for an image for the logout image1 = StringUtil.trimToNull(ServerConfigurationService.getString("logout.icon")); // since we are doing logout, cancel top.login topLogin = false; } // put out the links version if (!topLogin) { out.println(" " + ((image1 == null) ? message : "") + ""); if (logInOutUrl2 != null) { out.println(" " + ((image2 == null) ? message2 : "\""") + ""); } } // else put out the fields that will send to the login interface else { // find the login tool Tool loginTool = ToolManager.getTool("sakai.login"); String eidWording = null; String pwWording = null; eidWording = StringUtil.trimToNull(rb.getString("log.userid")); pwWording = StringUtil.trimToNull(rb.getString("log.pass")); if (eidWording == null) eidWording = "eid"; if (pwWording == null) pwWording = "pw"; String loginWording = rb.getString("log.login"); out.println("
"); out.println(eidWording + ""); out.println(pwWording + ""); out.println("
"); // setup for the redirect after login session.setAttribute(Tool.HELPER_DONE_URL, ServerConfigurationService.getPortalUrl()); } } protected void includePage(PrintWriter out, HttpServletRequest req, SitePage page, String toolContextPath, String wrapperClass) throws IOException { // divs to wrap the tools out.println("
"); // get the tools on this first column of page if (page.getLayout() == SitePage.LAYOUT_DOUBLE_COL) { out.println("
"); } else { out.println("
"); } String currentUserId = SessionManager.getCurrentSessionUserId(); String activeUserRoleInSite = getActiveUserRoleInSite(currentUserId, page.getContainingSite()); List tools = page.getTools(0); for (Iterator i = tools.iterator(); i.hasNext();) { ToolConfiguration placement = (ToolConfiguration) i.next(); // check if current user have permission to see page // will draw page button if it have permission over at least one tool if(SessionManager.getCurrentSessionUserId() != null && !SecurityService.isSuperUser()){ Tool tool = placement.getTool(); if(!isToolAllowedForRole(tool, activeUserRoleInSite)) continue; } // for this tool invocation, form the servlet context and path info String contextPath = toolContextPath + "/tool/" + Web.escapeUrl(placement.getId()); String pathInfo = null; // invoke the tool includeTool(out, req, placement); } out.println("
"); // do the second column if needed if (page.getLayout() == SitePage.LAYOUT_DOUBLE_COL) { out.println("
"); tools = page.getTools(1); for (Iterator i = tools.iterator(); i.hasNext();) { ToolConfiguration placement = (ToolConfiguration) i.next(); // check if current user have permission to see page // will draw page button if it have permission over at least one tool if(SessionManager.getCurrentSessionUserId() != null && !SecurityService.isSuperUser()){ Tool tool = placement.getTool(); if(!isToolAllowedForRole(tool, activeUserRoleInSite)) continue; } // for this tool invocation, form the servlet context and path info String contextPath = toolContextPath + "/tool/" + Web.escapeUrl(placement.getId()); String pathInfo = null; // invoke the tool includeTool(out, req, placement); } out.println("
"); } out.println("
"); } protected void includePageNav(PrintWriter out, HttpServletRequest req, Session session, Site site, SitePage page, String toolContextPath, String portalPrefix) throws IOException { String presenceUrl = Web.returnUrl(req, "/presence/" + Web.escapeUrl(site.getId())); String pageUrl = Web.returnUrl(req, "/" + portalPrefix + "/" + Web.escapeUrl(site.getId()) + "/page/"); String pagePopupUrl = Web.returnUrl(req, "/page/"); boolean showPresence = ServerConfigurationService.getBoolean("display.users.present", true); boolean loggedIn = session.getUserId() != null; String iconUrl = site.getIconUrlFull(); boolean published = site.isPublished(); String type = site.getType(); out.println("
"); out.println("
"); if (!published) { out.println("

" + "unpublished site" + "

"); } if (type != null) { if (type.equals("project")) { out.println("

" + type + "

"); } } if (iconUrl != null) { out.println(" "); } out.println("
"); // gsilver - target of "jump to tools" link, header out.println(" "); out.println("

" + Web.escapeHtml(rb.getString("sit.toolshead")) + "

"); out.println("
"); out.println(" "); out.println("
"); if (showPresence && loggedIn) { out.println("
"); out.println(Web.escapeHtml(rb.getString("sit.presencetitle"))); out.println("
"); out.println(" "); } out.println("
"); // gsilver - target of "jump to content" link and header for content out.println("

" + Web.escapeHtml(rb.getString("sit.contentshead")) + "

"); out.println(" "); } protected String getActiveUserRoleInSite(String userId, Site site) { if(userId == null || SecurityService.isSuperUser()) return null; Role r = site.getUserRole(userId); if(r != null) return r.getId(); else return ""; } /** * Checks if a given user has permissions access a tool in a site. * This is checked agains the following tags in tool xml file:
*
*
* Both, one or none of this configuration tags can be specified. By default, * an user has permissions to see the tool in site.
* Permissions are checked in the order: Allow, Deny. * @param tool Tool to check permissions on. * @param roleId Current user's role. * @return Whether user has permissions to this tool in this site. */ protected boolean isToolAllowedForRole(Tool tool, String roleId) { String TOOL_CFG_ROLES_ALLOW = "roles.allow"; String TOOL_CFG_ROLES_DENY = "roles.deny"; Properties roleConfig = tool.getRegisteredConfig(); String toolTitle = tool.getTitle(); boolean allowRuleSpecified = roleConfig.containsKey(TOOL_CFG_ROLES_ALLOW); boolean denyRuleSpecified = roleConfig.containsKey(TOOL_CFG_ROLES_DENY); // allow by default, when no config keys are present if(!allowRuleSpecified && !allowRuleSpecified) return true; boolean allowed = true; if(allowRuleSpecified){ allowed = false; boolean found = false; String[] result = roleConfig.getProperty(TOOL_CFG_ROLES_ALLOW).split("\\,"); for (int x=0; x" + Web.escapeHtml(rb.getString("sit.accessibility")) + ""); } out.println("" + Web.escapeHtml(rb.getString("sit.jumpcontent")) + ""); out.println("" + Web.escapeHtml(rb.getString("sit.jumptools")) + ""); out.println("" + Web.escapeHtml(rb.getString("sit.jumpworksite")) + ""); out.println(""); out.println(""); } protected void includeTabs(PrintWriter out, HttpServletRequest req, Session session, String siteId, String prefix, boolean addLogout) throws IOException { // for skinning String siteType = calcSiteType(siteId); // is the current site the end user's My Workspace? boolean curMyWorkspace = ((siteId == null) || (SiteService.isUserSite(siteId) && (SiteService.getSiteUserId(siteId) .equals(session.getUserId())))); // if this is a My Workspace, it gets its own tab and should not be considered in the other tab logic if (curMyWorkspace) siteId = null; // collect the user's sites List mySites = SiteService.getSites(org.sakaiproject.service.legacy.site.SiteService.SelectionType.ACCESS, null, null, null, org.sakaiproject.service.legacy.site.SiteService.SortType.TITLE_ASC, null); // collect the user's preferences int prefTabs = 4; List prefExclude = new Vector(); List prefOrder = new Vector(); if (session.getUserId() != null) { Preferences prefs = PreferencesService.getPreferences(session.getUserId()); ResourceProperties props = prefs.getProperties("sakai.portal.sitenav"); try { prefTabs = (int) props.getLongProperty("tabs"); } catch (Exception any) { } List l = props.getPropertyList("exclude"); if (l != null) { prefExclude = l; } l = props.getPropertyList("order"); if (l != null) { prefOrder = l; } } // the number of tabs to display int tabsToDisplay = prefTabs; // remove all in exclude from mySites mySites.removeAll(prefExclude); // re-order mySites to have order first, the rest later List ordered = new Vector(); for (Iterator i = prefOrder.iterator(); i.hasNext();) { String id = (String) i.next(); // find this site in the mySites list int pos = indexOf(id, mySites); if (pos != -1) { // move it from mySites to order Site s = (Site) mySites.get(pos); ordered.add(s); mySites.remove(pos); } } // pick up the rest of the sites ordered.addAll(mySites); mySites = ordered; // split into 2 lists - the first n, and the rest List moreSites = new Vector(); if (mySites.size() > tabsToDisplay) { int remove = mySites.size() - tabsToDisplay; for (int i = 0; i < remove; i++) { Site site = (Site) mySites.get(tabsToDisplay); // add to more unless it's the current site (it will get an extra tag) if (!site.getId().equals(siteId)) { moreSites.add(site); } // remove from the display list mySites.remove(tabsToDisplay); } } // if more has just one, put it back on the main list if (moreSites.size() == 1) { mySites.add(moreSites.get(0)); moreSites.clear(); } // check if the current site is missing from the main list String extraTitle = null; if (siteId != null) { boolean extra = true; for (Iterator i = mySites.iterator(); i.hasNext();) { Site site = (Site) i.next(); if (site.getId().equals(siteId)) { extra = false; break; } } if (extra) { try { Site site = SiteService.getSite(siteId); extraTitle = site.getTitle(); } catch (IdUnusedException e) { M_log.warn("doSiteNav: cur site not found: " + siteId); } } } String cssClass = (siteType != null) ? "tabHolder " + siteType : "tabHolder"; out.println("
"); out.println(" "); out.println(" "); out.println(" "); // more dropdown if (moreSites.size() > 0) { out.println(" "); } if (addLogout) { String logoutUrl = Web.serverUrl(req) + "/portal/logout_gallery"; out.println(""); } out.println(" "); out.println("
"); // gsilver - target for "jump to tabs" link and header out.println(" "); out.println("

" + Web.escapeHtml(rb.getString("sit.worksiteshead")) + "

"); out.println(" "); out.println("
" + Web.escapeHtml(rb.getString("sit.selectmessage")) + ""); out.println(" "); out.println(" "); out.println(" " + Web.escapeHtml(rb.getString("sit.log")) + ""); out.println("
"); out.println("

"); if (addLogout) { } else { out.println("
"); } } protected void includeTool(PrintWriter out, HttpServletRequest req, ToolConfiguration placement) throws IOException { // Note: at present (sakai 2.0), we don't fully support aggregation - tools, such as // velocity based tools, might do some things to the response object to interfere // with subsequent tool use of the object. We will have to have more protective // response objects for each tool. For now, tools get forwarded, not included. // This means that Charon will cheat about placing the tool's initial (aggregated) // display; the title and main iframes. Varuna did, too! -ggolden // find the tool registered for this ActiveTool tool = ActiveToolManager.getActiveTool(placement.getTool().getId()); if (tool == null) { // doError(req, res, session); return; } // let the tool do some the work (include) (see note above) // tool.include(req, res, siteTool, toolContextPath, toolPathInfo); String toolUrl = Web.returnUrl(req, "/tool/" + Web.escapeUrl(placement.getId())); String titleUrl = Web.returnUrl(req, "/title/" + Web.escapeUrl(placement.getId())); String titleString = Web.escapeHtml(placement.getTitle()); // boolean portalHandlesTitleFrame = !"false".equals(placement.getConfig().getProperty(TOOLCONFIG_PORTAL_HANDLES_TITLEBAR)); // if (!portalHandlesTitleFrame) // { // // let the tool output its own title frame // titleUrl = toolUrl + "?panel=Title"; // } // this is based on what varuna is currently putting out out.println("
"); out.println(""); out.println(""); out.println("
"); out.println("
"); out.println(""); out.println("
"); } protected void includeWorksite(PrintWriter out, HttpServletRequest req, Session session, Site site, SitePage page, String toolContextPath, String portalPrefix) throws IOException { // add the page navigation with presence includePageNav(out, req, session, site, page, toolContextPath, portalPrefix); // add the page includePage(out, req, page, toolContextPath, "content"); } /** * Initialize the servlet. * * @param config * The servlet config. * @throws ServletException */ public void init(ServletConfig config) throws ServletException { super.init(config); M_log.info("init()"); } /** * TODO: I'm not sure why this has to be different from doLogin... * * @param req * @param res * @param session * @throws IOException */ protected void postLogin(HttpServletRequest req, HttpServletResponse res, Session session, String loginPath) throws IOException { ActiveTool tool = ActiveToolManager.getActiveTool("sakai.login"); String context = req.getContextPath() + req.getServletPath() + "/" + loginPath; tool.help(req, res, context, "/" + loginPath); } /** * Output some session information * * @param out * The print writer * @param html * If true, output in HTML, else in text. */ protected void showSession(PrintWriter out, boolean html) { // get the current user session information Session s = SessionManager.getCurrentSession(); if (s == null) { out.println("no session established"); if (html) out.println("
"); } else { out.println("session: " + s.getId() + " user id: " + s.getUserId() + " enterprise id: " + s.getUserEid() + " started: " + DateFormat.getDateInstance().format(new Date(s.getCreationTime())) + " accessed: " + DateFormat.getDateInstance().format(new Date(s.getLastAccessedTime())) + " inactive after: " + s.getMaxInactiveInterval()); if (html) out.println("
"); } ToolSession ts = SessionManager.getCurrentToolSession(); if (ts == null) { out.println("no tool session established"); if (html) out.println("
"); } else { out.println("tool session: " + ts.getId() + " started: " + DateFormat.getDateInstance().format(new Date(ts.getCreationTime())) + " accessed: " + DateFormat.getDateInstance().format(new Date(ts.getLastAccessedTime()))); if (html) out.println("
"); } } protected PrintWriter startResponse(HttpServletResponse res, String title, String skin) throws IOException { // headers res.setContentType("text/html; charset=UTF-8"); res.addDateHeader("Expires", System.currentTimeMillis() - (1000L * 60L * 60L * 24L * 365L)); res.addDateHeader("Last-Modified", System.currentTimeMillis()); res.addHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"); res.addHeader("Pragma", "no-cache"); // get the writer PrintWriter out = res.getWriter(); // form the head out.println("" + "" + " " + " "); // pick the one full portal skin if (skin == null) { skin = ServerConfigurationService.getString("skin.default"); } String skinRepo = ServerConfigurationService.getString("skin.repo"); out.println(" "); out.println(" " + " " + Web.escapeHtml(title) + "" + " " + " "); // start the body out.println(""); return out; } /** * Returns the type ("course", "project", "workspace", "mySpecialSiteType", etc) of the given site; special handling of returning "workspace" for user workspace sites. This method is tightly coupled to site skinning. */ private String calcSiteType(String siteId) { String siteType = null; if (siteId != null && siteId.length() != 0) { if (SiteService.isUserSite(siteId)) { siteType = "workspace"; } else { try { siteType = SiteService.getSite(siteId).getType(); } catch (IdUnusedException ex) { // ignore, the site wasn't found } } } if (siteType != null && siteType.trim().length() == 0) siteType = null; return siteType; } /** * Find the site in the list that has this id - return the position. * * @param value * The site id to find. * @param siteList * The list of Site objects. * @return The index position in siteList of the site with site id = value, or -1 if not found. */ protected int indexOf(String value, List siteList) { for (int i = 0; i < siteList.size(); i++) { Site site = (Site) siteList.get(i); if (site.equals(value)) { return i; } } return -1; } }