0001: /**********************************************************************************
0002: * $URL: https://source.sakaiproject.org/svn/portal/tags/sakai_2-4-1/portal-impl/impl/src/java/org/sakaiproject/portal/charon/CharonPortal.java $
0003: * $Id: CharonPortal.java 29196 2007-04-19 03:00:16Z ajpoland@iupui.edu $
0004: ***********************************************************************************
0005: *
0006: * Copyright (c) 2005, 2006 The Sakai Foundation.
0007: *
0008: * Licensed under the Educational Community License, Version 1.0 (the "License");
0009: * you may not use this file except in compliance with the License.
0010: * You may obtain a copy of the License at
0011: *
0012: * http://www.opensource.org/licenses/ecl1.php
0013: *
0014: * Unless required by applicable law or agreed to in writing, software
0015: * distributed under the License is distributed on an "AS IS" BASIS,
0016: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: * See the License for the specific language governing permissions and
0018: * limitations under the License.
0019: *
0020: **********************************************************************************/package org.sakaiproject.portal.charon;
0021:
0022: import java.io.IOException;
0023: import java.io.PrintWriter;
0024: import java.text.DateFormat;
0025: import java.util.Date;
0026: import java.util.Iterator;
0027: import java.util.List;
0028: import java.util.Properties;
0029: import java.util.Vector;
0030:
0031: import javax.servlet.ServletConfig;
0032: import javax.servlet.ServletException;
0033: import javax.servlet.http.HttpServlet;
0034: import javax.servlet.http.HttpServletRequest;
0035: import javax.servlet.http.HttpServletResponse;
0036:
0037: import org.apache.commons.logging.Log;
0038: import org.apache.commons.logging.LogFactory;
0039: import org.sakaiproject.authz.cover.SecurityService;
0040: import org.sakaiproject.component.cover.ServerConfigurationService;
0041: import org.sakaiproject.entity.api.ResourceProperties;
0042: import org.sakaiproject.exception.IdUnusedException;
0043: import org.sakaiproject.exception.PermissionException;
0044: import org.sakaiproject.portal.api.PortalService;
0045: import org.sakaiproject.portal.api.StoredState;
0046: import org.sakaiproject.portal.render.api.RenderResult;
0047: import org.sakaiproject.portal.render.cover.ToolRenderService;
0048: import org.sakaiproject.portal.util.ErrorReporter;
0049: import org.sakaiproject.portal.util.ToolURLManagerImpl;
0050: import org.sakaiproject.site.api.Site;
0051: import org.sakaiproject.site.api.SitePage;
0052: import org.sakaiproject.site.api.ToolConfiguration;
0053: import org.sakaiproject.site.cover.SiteService;
0054: import org.sakaiproject.thread_local.cover.ThreadLocalManager;
0055: import org.sakaiproject.tool.api.ActiveTool;
0056: import org.sakaiproject.tool.api.Placement;
0057: import org.sakaiproject.tool.api.Session;
0058: import org.sakaiproject.tool.api.Tool;
0059: import org.sakaiproject.tool.api.ToolException;
0060: import org.sakaiproject.tool.api.ToolSession;
0061: import org.sakaiproject.tool.api.ToolURL;
0062: import org.sakaiproject.tool.cover.ActiveToolManager;
0063: import org.sakaiproject.tool.cover.SessionManager;
0064: import org.sakaiproject.tool.cover.ToolManager;
0065: import org.sakaiproject.user.api.Preferences;
0066: import org.sakaiproject.user.api.UserNotDefinedException;
0067: import org.sakaiproject.user.cover.PreferencesService;
0068: import org.sakaiproject.user.cover.UserDirectoryService;
0069: import org.sakaiproject.util.BasicAuth;
0070: import org.sakaiproject.util.ResourceLoader;
0071: import org.sakaiproject.util.StringUtil;
0072: import org.sakaiproject.util.Web;
0073:
0074: /**
0075: * <p>
0076: * Charon is the Sakai Site based portal.
0077: * </p>
0078: * @since Sakai 2.0
0079: * @version $Rev: 29196 $
0080: *
0081: */
0082: public class CharonPortal extends HttpServlet {
0083:
0084: /** Our log (commons). */
0085: private static Log M_log = LogFactory.getLog(CharonPortal.class);
0086:
0087: /** messages. */
0088: private static ResourceLoader rb = new ResourceLoader("sitenav");
0089:
0090: /**
0091: * Session attribute root for storing a site's last page visited - just
0092: * append the site id.
0093: */
0094: protected static final String ATTR_SITE_PAGE = "sakai.portal.site.";
0095:
0096: /**
0097: * Parameter value to allow anonymous users of gallery mode to be sent to
0098: * the gateway site as anonymous user (like the /portal URL) instead of
0099: * making them log in (like worksite, site, and tool URLs).
0100: */
0101: protected static final String PARAM_FORCE_LOGIN = "force.login";
0102:
0103: /** Configuration option to enable/disable state reset on navigation change */
0104: protected static final String CONFIG_AUTO_RESET = "portal.experimental.auto.reset";
0105:
0106: /** Parameter value to indicate to look up a tool ID within a site */
0107: protected static final String PARAM_SAKAI_SITE = "sakai.site";
0108:
0109: /** ThreadLocal attribute set while we are processing an error. */
0110: protected static final String ATTR_ERROR = "org.sakaiproject.portal.error";
0111:
0112: /** Error response modes. */
0113: protected static final int ERROR_SITE = 0;
0114:
0115: protected static final int ERROR_GALLERY = 1;
0116:
0117: protected static final int ERROR_WORKSITE = 2;
0118:
0119: /**
0120: * Names of tool config/registration attributes that control the rendering
0121: * of the tool's titlebar
0122: */
0123: private static final String TOOLCONFIG_SHOW_RESET_BUTTON = "reset.button";
0124:
0125: private static final String TOOLCONFIG_SHOW_HELP_BUTTON = "help.button";
0126:
0127: private static final String TOOLCONFIG_HELP_DOCUMENT_ID = "help.id";
0128:
0129: private static final String TOOLCONFIG_HELP_DOCUMENT_URL = "help.url";
0130:
0131: private BasicAuth basicAuth = null;
0132:
0133: private boolean enableDirect = false;
0134:
0135: private PortalService portalService;
0136:
0137: /**
0138: * Shutdown the servlet.
0139: */
0140: public void destroy() {
0141: M_log.info("destroy()");
0142:
0143: super .destroy();
0144: }
0145:
0146: protected void doError(HttpServletRequest req,
0147: HttpServletResponse res, Session session, int mode)
0148: throws ToolException, IOException {
0149: if (ThreadLocalManager.get(ATTR_ERROR) == null) {
0150: ThreadLocalManager.set(ATTR_ERROR, ATTR_ERROR);
0151:
0152: // send to the error site
0153: switch (mode) {
0154: case ERROR_SITE: {
0155: doSite(req, res, session, "!error", null, req
0156: .getContextPath()
0157: + req.getServletPath());
0158: break;
0159: }
0160: case ERROR_GALLERY: {
0161: doGallery(req, res, session, "!error", null, req
0162: .getContextPath()
0163: + req.getServletPath());
0164: break;
0165: }
0166: case ERROR_WORKSITE: {
0167: doWorksite(req, res, session, "!error", null, req
0168: .getContextPath()
0169: + req.getServletPath());
0170: break;
0171: }
0172: }
0173: return;
0174: }
0175:
0176: // error and we cannot use the error site...
0177:
0178: // form a context sensitive title
0179: String title = ServerConfigurationService
0180: .getString("ui.service")
0181: + " : Portal";
0182:
0183: // start the response
0184: PrintWriter out = startResponse(res, title, null, false);
0185:
0186: // Show session information
0187: out.println("<h2>Session</h2>");
0188: showSession(out, true);
0189:
0190: out.println("<h2>Unknown Request</h2>");
0191: Web.snoop(out, true, getServletConfig(), req);
0192:
0193: // end the response
0194: endResponse(out);
0195: }
0196:
0197: protected void doThrowableError(HttpServletRequest req,
0198: HttpServletResponse res, Throwable t) {
0199: ErrorReporter err = new ErrorReporter();
0200: err.report(req, res, t);
0201: }
0202:
0203: protected void doGallery(HttpServletRequest req,
0204: HttpServletResponse res, Session session, String siteId,
0205: String pageId, String toolContextPath)
0206: throws ToolException, IOException {
0207: // check to default site id
0208: if (siteId == null) {
0209: if (session.getUserId() == null) {
0210: String forceLogin = req.getParameter(PARAM_FORCE_LOGIN);
0211: if (forceLogin == null
0212: || "yes".equalsIgnoreCase(forceLogin)
0213: || "true".equalsIgnoreCase(forceLogin)) {
0214: doLogin(req, res, session, req.getPathInfo(), false);
0215: return;
0216: }
0217: siteId = ServerConfigurationService.getGatewaySiteId();
0218: } else {
0219: siteId = SiteService.getUserSiteId(session.getUserId());
0220: }
0221: }
0222:
0223: // if no page id, see if there was a last page visited for this site
0224: if (pageId == null) {
0225: pageId = (String) session.getAttribute(ATTR_SITE_PAGE
0226: + siteId);
0227: }
0228:
0229: // find the site, for visiting
0230: Site site = null;
0231: try {
0232: site = getSiteVisit(siteId);
0233: } catch (IdUnusedException e) {
0234: doError(req, res, session, ERROR_GALLERY);
0235: return;
0236: } catch (PermissionException e) {
0237: // if not logged in, give them a chance
0238: if (session.getUserId() == null) {
0239: doLogin(req, res, session, req.getPathInfo(), false);
0240: } else {
0241: doError(req, res, session, ERROR_GALLERY);
0242: }
0243: return;
0244: }
0245:
0246: // find the page, or use the first page if pageId not found
0247: SitePage page = site.getPage(pageId);
0248: if (page == null) {
0249: List pages = site.getOrderedPages();
0250: if (!pages.isEmpty()) {
0251: page = (SitePage) pages.get(0);
0252: }
0253: }
0254: if (page == null) {
0255: doError(req, res, session, ERROR_GALLERY);
0256: return;
0257: }
0258:
0259: // store the last page visited
0260: session.setAttribute(ATTR_SITE_PAGE + siteId, page.getId());
0261:
0262: // form a context sensitive title
0263: String title = ServerConfigurationService
0264: .getString("ui.service")
0265: + " : " + site.getTitle() + " : " + page.getTitle();
0266:
0267: // start the response
0268: PrintWriter out = startResponse(res, title, site.getSkin(),
0269: true);
0270:
0271: // the 'little' top area
0272: includeGalleryNav(out, req, session, siteId);
0273:
0274: String siteType = calcSiteType(siteId);
0275: out.println("<div id=\"container\""
0276: + ((siteType != null) ? " class=\"" + siteType + "\""
0277: : "") + ">");
0278:
0279: includeWorksite(req, res, session, site, page, toolContextPath,
0280: "gallery");
0281: out.println("<div>");
0282:
0283: includeBottom(out);
0284:
0285: // end the response
0286: endResponse(out);
0287: }
0288:
0289: protected void doGalleryTabs(HttpServletRequest req,
0290: HttpServletResponse res, Session session, String siteId)
0291: throws IOException {
0292: String skin = SiteService.getSiteSkin(siteId);
0293:
0294: // start the response
0295: PrintWriter out = startResponse(res, "Site Navigation", skin,
0296: false);
0297:
0298: // Remove the logout button from gallery since it is designed to be
0299: // included within
0300: // some other application (like a portal) which will want to control
0301: // logout.
0302:
0303: // includeTabs(out, req, session, siteId, "gallery", true);
0304: includeTabs(out, req, session, siteId, "gallery", false);
0305:
0306: // end the response
0307: endResponse(out);
0308: }
0309:
0310: /**
0311: * Respond to navigation / access requests.
0312: *
0313: * @param req
0314: * The servlet request.
0315: * @param res
0316: * The servlet response.
0317: * @throws ServletException
0318: * @throws IOException
0319: */
0320: protected void doGet(HttpServletRequest req, HttpServletResponse res)
0321: throws ServletException, IOException {
0322: boolean resetDone = false;
0323: try {
0324: basicAuth.doLogin(req);
0325: // get the Sakai session
0326: Session session = SessionManager.getCurrentSession();
0327:
0328: // recognize what to do from the path
0329: String option = req.getPathInfo();
0330:
0331: // if missing, set it to home or gateway
0332: if ((option == null) || ("/".equals(option))) {
0333: if (session.getUserId() == null) {
0334: option = "/site/"
0335: + ServerConfigurationService
0336: .getGatewaySiteId();
0337: } else {
0338: option = "/site/"
0339: + SiteService.getUserSiteId(session
0340: .getUserId());
0341: }
0342: }
0343:
0344: // get the parts (the first will be "")
0345: String[] parts = option.split("/");
0346:
0347: // recognize and dispatch the 'tool' option: [1] = "tool", [2] =
0348: // placement id (of a site's tool placement), rest for the tool
0349: if ((parts.length > 2) && (parts[1].equals("tool"))) {
0350: // Resolve the placements of the form
0351: // /portal/tool/sakai.resources?sakai.site=~csev
0352: String toolPlacement = getPlacement(req, res, session,
0353: parts[2], false);
0354: if (toolPlacement == null) {
0355: return;
0356: }
0357: parts[2] = toolPlacement;
0358:
0359: doTool(req, res, session, parts[2], req
0360: .getContextPath()
0361: + req.getServletPath()
0362: + Web.makePath(parts, 1, 3), Web.makePath(
0363: parts, 3, parts.length));
0364: } else if (enableDirect && (parts.length > 2)
0365: && (parts[1].equals("directtool"))) {
0366: // Resolve the placements of the form
0367: // /portal/tool/sakai.resources?sakai.site=~csev
0368: String toolPlacement = getPlacement(req, res, session,
0369: parts[2], false);
0370: if (toolPlacement == null) {
0371: return;
0372: }
0373: parts[2] = toolPlacement;
0374:
0375: doDirectTool(req, res, session, parts[2], req
0376: .getContextPath()
0377: + req.getServletPath()
0378: + Web.makePath(parts, 1, 3), Web.makePath(
0379: parts, 3, parts.length));
0380: }
0381:
0382: // These reet urls simply set a session value to indicate to reset
0383: // state and then redirect
0384: // This is necessary os that hte URL is clean and we do not see
0385: // resets on refresh
0386: else if ((parts.length > 2)
0387: && (parts[1].equals("tool-reset"))) {
0388: String toolUrl = req.getContextPath() + "/tool"
0389: + Web.makePath(parts, 2, parts.length);
0390: // Make sure to add the parameters such as panel=Main
0391: String queryString = req.getQueryString();
0392: if (queryString != null) {
0393: toolUrl = toolUrl + "?" + queryString;
0394: }
0395: portalService.setResetState("true");
0396: resetDone = true;
0397: res.sendRedirect(toolUrl);
0398: }
0399:
0400: /**
0401: * Title frames were no longer used in 2.3 and are not supported in
0402: * 2.4 so we emit a WARN message here to help people with derived
0403: * classes figure out the new way.
0404: */
0405:
0406: // TODO: Remove after 2.4
0407: else if ((parts.length > 2) && (parts[1].equals("title"))) {
0408: // Resolve the placements of the form
0409: // /portal/title/sakai.resources?sakai.site=~csev
0410: String toolPlacement = getPlacement(req, res, session,
0411: parts[2], false);
0412: if (toolPlacement == null) {
0413: return;
0414: }
0415: parts[2] = toolPlacement;
0416:
0417: doTitle(req, res, session, parts[2], req
0418: .getContextPath()
0419: + req.getServletPath()
0420: + Web.makePath(parts, 1, 3), Web.makePath(
0421: parts, 3, parts.length));
0422: }
0423:
0424: // recognize a dispatch the 'page' option (tools on a page)
0425: else if ((parts.length == 3) && (parts[1].equals("page"))) {
0426: // Resolve the placements of the form
0427: // /portal/page/sakai.resources?sakai.site=~csev
0428: String pagePlacement = getPlacement(req, res, session,
0429: parts[2], true);
0430: if (pagePlacement == null) {
0431: return;
0432: }
0433: parts[2] = pagePlacement;
0434:
0435: doPage(req, res, session, parts[2], req
0436: .getContextPath()
0437: + req.getServletPath());
0438: }
0439:
0440: // recognize a dispatch the 'worksite' option (pages navigation +
0441: // tools on a page)
0442: else if ((parts.length >= 3)
0443: && (parts[1].equals("worksite"))) {
0444: // recognize an optional page/pageid
0445: String pageId = null;
0446: if ((parts.length == 5) && (parts[3].equals("page"))) {
0447: pageId = parts[4];
0448: }
0449:
0450: doWorksite(req, res, session, parts[2], pageId, req
0451: .getContextPath()
0452: + req.getServletPath());
0453: }
0454:
0455: // recognize a dispatch the 'gallery' option (site tabs + pages
0456: // navigation + tools on a page)
0457: else if ((parts.length >= 2)
0458: && (parts[1].equals("gallery"))) {
0459: // recognize an optional page/pageid
0460: String pageId = null;
0461: if ((parts.length == 5) && (parts[3].equals("page"))) {
0462: pageId = parts[4];
0463: }
0464:
0465: // site might be specified
0466: String siteId = null;
0467: if (parts.length >= 3) {
0468: siteId = parts[2];
0469: }
0470:
0471: doGallery(req, res, session, siteId, pageId, req
0472: .getContextPath()
0473: + req.getServletPath());
0474: }
0475:
0476: // recognize a dispatch the 'site' option (site logo and tabs +
0477: // pages navigation + tools on a page)
0478: else if ((parts.length >= 2) && (parts[1].equals("site"))) {
0479: // recognize an optional page/pageid
0480: String pageId = null;
0481: if ((parts.length == 5) && (parts[3].equals("page"))) {
0482: pageId = parts[4];
0483: }
0484:
0485: // site might be specified
0486: String siteId = null;
0487: if (parts.length >= 3) {
0488: siteId = parts[2];
0489: }
0490:
0491: doSite(req, res, session, siteId, pageId, req
0492: .getContextPath()
0493: + req.getServletPath());
0494: }
0495:
0496: // recognize site tabs
0497: else if ((parts.length == 3)
0498: && (parts[1].equals("site_tabs"))) {
0499: doSiteTabs(req, res, session, parts[2]);
0500: }
0501:
0502: // recognize gallery tabs
0503: else if ((parts.length == 3)
0504: && (parts[1].equals("gallery_tabs"))) {
0505: doGalleryTabs(req, res, session, parts[2]);
0506: }
0507:
0508: // recognize nav login
0509: else if ((parts.length == 3)
0510: && (parts[1].equals("nav_login"))) {
0511: doNavLogin(req, res, session, parts[2]);
0512: }
0513:
0514: // recognize nav login for the gallery
0515: else if ((parts.length == 3)
0516: && (parts[1].equals("nav_login_gallery"))) {
0517: doNavLoginGallery(req, res, session, parts[2]);
0518: }
0519:
0520: // recognize presence
0521: else if ((parts.length >= 3)
0522: && (parts[1].equals("presence"))) {
0523: doPresence(req, res, session, parts[2], req
0524: .getContextPath()
0525: + req.getServletPath()
0526: + Web.makePath(parts, 1, 3), Web.makePath(
0527: parts, 3, parts.length));
0528: }
0529:
0530: // recognize help
0531: else if ((parts.length >= 2) && (parts[1].equals("help"))) {
0532: doHelp(req, res, session, req.getContextPath()
0533: + req.getServletPath()
0534: + Web.makePath(parts, 1, 2), Web.makePath(
0535: parts, 2, parts.length));
0536: }
0537:
0538: // recognize and dispatch the 'login' option
0539: else if ((parts.length == 2)
0540: && (parts[1].equals("relogin"))) {
0541: // Note: here we send a null path, meaning we will NOT set it as
0542: // a possible return path
0543: // we expect we are in the middle of a login screen processing,
0544: // and it's already set (user login button is "ulogin") -ggolden
0545: doLogin(req, res, session, null, false);
0546: }
0547:
0548: // recognize and dispatch the 'login' option
0549: else if ((parts.length == 2) && (parts[1].equals("login"))) {
0550: doLogin(req, res, session, "", false);
0551: }
0552:
0553: // recognize and dispatch the 'login' options
0554: else if ((parts.length == 2)
0555: && ((parts[1].equals("xlogin")))) {
0556: doLogin(req, res, session, "", true);
0557: }
0558:
0559: // recognize and dispatch the 'login' option for gallery
0560: else if ((parts.length == 2)
0561: && (parts[1].equals("login_gallery"))) {
0562: doLogin(req, res, session, "/gallery", false);
0563: }
0564:
0565: // recognize and dispatch the 'logout' option
0566: else if ((parts.length == 2) && (parts[1].equals("logout"))) {
0567: doLogout(req, res, session, null);
0568: }
0569:
0570: // recognize and dispatch the 'logout' option for gallery
0571: else if ((parts.length == 2)
0572: && (parts[1].equals("logout_gallery"))) {
0573: doLogout(req, res, session, "/gallery");
0574: }
0575:
0576: // recognize error done
0577: else if ((parts.length >= 2)
0578: && (parts[1].equals("error-reported"))) {
0579: doErrorDone(req, res);
0580: }
0581:
0582: // handle an unrecognized request
0583: else {
0584: doError(req, res, session, ERROR_SITE);
0585: }
0586: } catch (Throwable t) {
0587: doThrowableError(req, res, t);
0588: }
0589:
0590: // Make sure to clear any reset State at the end of the request unless
0591: // we *just* set it
0592: if (!resetDone) {
0593: portalService.setResetState(null);
0594: }
0595:
0596: }
0597:
0598: /**
0599: * Title frames were no longer used in 2.3 and are not supported in 2.4 so
0600: * these methods are made private to notify derived classes. they can be
0601: * removed for 2.5 - csev
0602: */
0603:
0604: protected void doTitle(HttpServletRequest req,
0605: HttpServletResponse res, Session session,
0606: String placementId, String toolContextPath,
0607: String toolPathInfo) throws ToolException, IOException {
0608: // find the tool from some site
0609: ToolConfiguration siteTool = SiteService.findTool(placementId);
0610: if (siteTool == null) {
0611: doError(req, res, session, ERROR_WORKSITE);
0612: return;
0613: }
0614:
0615: // find the tool registered for this
0616: ActiveTool tool = ActiveToolManager.getActiveTool(siteTool
0617: .getToolId());
0618: if (tool == null) {
0619: doError(req, res, session, ERROR_WORKSITE);
0620: return;
0621: }
0622:
0623: // don't check permissions when just displaying the title...
0624: // // permission check - visit the site (unless the tool is configured
0625: // to bypass)
0626: // if (tool.getAccessSecurity() == Tool.AccessSecurity.PORTAL)
0627: // {
0628: // Site site = null;
0629: // try
0630: // {
0631: // site = SiteService.getSiteVisit(siteTool.getSiteId());
0632: // }
0633: // catch (IdUnusedException e)
0634: // {
0635: // doError(req, res, session, ERROR_WORKSITE);
0636: // return;
0637: // }
0638: // catch (PermissionException e)
0639: // {
0640: // // if not logged in, give them a chance
0641: // if (session.getUserId() == null)
0642: // {
0643: // doLogin(req, res, session, req.getPathInfo(), false);
0644: // }
0645: // else
0646: // {
0647: // doError(req, res, session, ERROR_WORKSITE);
0648: // }
0649: // return;
0650: // }
0651: // }
0652:
0653: includeTitle(tool, req, res, siteTool, siteTool.getSkin(),
0654: toolContextPath, toolPathInfo);
0655: }
0656:
0657: /**
0658: * Output the content of the title frame for a tool.
0659: */
0660: protected void includeTitle(ActiveTool tool,
0661: HttpServletRequest req, HttpServletResponse res,
0662: ToolConfiguration placement, String skin,
0663: String toolContextPath, String toolPathInfo)
0664: throws IOException {
0665:
0666: // TODO: After 2.3 and the background document is modified - this may no
0667: // longer be needed
0668: // as the title is simply in the background document
0669:
0670: res.setContentType("text/html; charset=UTF-8");
0671: res.addDateHeader("Expires", System.currentTimeMillis()
0672: - (1000L * 60L * 60L * 24L * 365L));
0673: res.addDateHeader("Last-Modified", System.currentTimeMillis());
0674: res
0675: .addHeader("Cache-Control",
0676: "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
0677: res.addHeader("Pragma", "no-cache");
0678:
0679: if (skin == null || skin.length() == 0)
0680: skin = ServerConfigurationService.getString("skin.default");
0681: String skinRepo = ServerConfigurationService
0682: .getString("skin.repo");
0683:
0684: // the title to display in the title frame
0685: String toolTitle = Web.escapeHtml(placement.getTitle());
0686:
0687: // for the reset button
0688: String resetActionUrl = toolContextPath + "?reset=true";
0689: boolean resetToolNow = "true".equals(req.getParameter("reset"));
0690: boolean showResetButton = !"false".equals(placement.getConfig()
0691: .getProperty(TOOLCONFIG_SHOW_RESET_BUTTON));
0692:
0693: // for the help button
0694: // get the help document ID from the tool config (tool registration
0695: // usually).
0696: // The help document ID defaults to the tool ID
0697: boolean helpEnabledGlobally = ServerConfigurationService
0698: .getBoolean("display.help.icon", true);
0699: boolean helpEnabledInTool = !"false".equals(placement
0700: .getConfig().getProperty(TOOLCONFIG_SHOW_HELP_BUTTON));
0701: boolean showHelpButton = helpEnabledGlobally
0702: && helpEnabledInTool;
0703:
0704: String helpActionUrl = "";
0705: if (showHelpButton) {
0706: String helpDocId = placement.getConfig().getProperty(
0707: TOOLCONFIG_HELP_DOCUMENT_ID);
0708: String helpDocUrl = placement.getConfig().getProperty(
0709: TOOLCONFIG_HELP_DOCUMENT_URL);
0710: if (helpDocUrl != null && helpDocUrl.length() > 0) {
0711: helpActionUrl = helpDocUrl;
0712: } else {
0713: if (helpDocId == null || helpDocId.length() == 0) {
0714: helpDocId = tool.getId();
0715: }
0716: helpActionUrl = ServerConfigurationService
0717: .getHelpUrl(helpDocId);
0718: }
0719: }
0720:
0721: PrintWriter out = res.getWriter();
0722:
0723: final String headHtml = "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">\n"
0724: + "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">\n"
0725: + " <head>\n"
0726: + " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />\n"
0727: + " <link href=\""
0728: + skinRepo
0729: + "/tool_base.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />\n"
0730: + " <link href=\""
0731: + skinRepo
0732: + "/"
0733: + skin
0734: + "/tool.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />\n"
0735: + " <meta http-equiv=\"Content-Style-Type\" content=\"text/css\" />\n"
0736: + " <script type=\"text/javascript\" language=\"JavaScript\" src=\""
0737: + getScriptPath()
0738: + "headscripts.js\"></script>\n"
0739: + " <title>"
0740: + toolTitle
0741: + "</title>\n"
0742: + " </head>\n" + " <body>\n";
0743: final String tailHtml = "</body></html>\n";
0744:
0745: out.write(headHtml);
0746:
0747: out.write("<div class=\"portletTitle\">\n");
0748: out.write("\t<div class=\"title\">\n");
0749: if (showResetButton) {
0750: out
0751: .write("\t\t<a href=\""
0752: + resetActionUrl
0753: + "\" title=\""
0754: + Web.escapeHtml(rb.getString("sit_reset"))
0755: + "\"><img src=\"/library/image/transparent.gif\" alt=\""
0756: + Web.escapeHtml(rb.getString("sit_reset"))
0757: + "\" border=\"1\" /></a>");
0758: }
0759:
0760: out.write("<h2>" + toolTitle + "\n" + "\t</h2></div>\n");
0761: out.write("\t<div class=\"action\">\n");
0762: if (showHelpButton) {
0763: out.write(makeHelpButton(helpActionUrl));
0764: }
0765:
0766: out.write("\t</div>\n");
0767: out.write("</div>\n");
0768:
0769: if (resetToolNow) {
0770: // cause main tool frame to be reset
0771:
0772: // clear the session data associated with the tool - should reset
0773: // the tool
0774: Session s = SessionManager.getCurrentSession();
0775: ToolSession ts = s.getToolSession(placement.getId());
0776: ts.clearAttributes();
0777:
0778: // redirect the main tool frame back to the initial tool URL.
0779: String mainFrameId = Web.escapeJavascript("Main"
0780: + placement.getId());
0781: String mainFrameUrl = ServerConfigurationService
0782: .getToolUrl()
0783: + "/"
0784: + Web.escapeUrl(placement.getId())
0785: + "?panel=Main";
0786:
0787: out
0788: .write("<script type=\"text/javascript\" language=\"JavaScript\">\n");
0789: out.write("try\n");
0790: out.write("{\n");
0791: out.write(" if (parent." + mainFrameId
0792: + ".location.toString().length > 1)\n");
0793: out.write(" {\n");
0794: out.write(" parent." + mainFrameId + ".location = '"
0795: + mainFrameUrl + "';\n");
0796: out.write(" }\n");
0797: out.write("}\n");
0798: out.write("catch (e1)\n");
0799: out.write("{\n");
0800: out.write(" try\n");
0801: out.write(" {\n");
0802: out.write(" if (parent.parent." + mainFrameId
0803: + ".location.toString().length > 1)\n");
0804: out.write(" {\n");
0805: out.write(" parent.parent." + mainFrameId
0806: + ".location = '" + mainFrameUrl + "';\n");
0807: out.write(" }\n");
0808: out.write(" }\n");
0809: out.write(" catch (e2)\n");
0810: out.write(" {\n");
0811: out.write(" }\n");
0812: out.write("}\n");
0813: out.write("</script>\n");
0814: }
0815:
0816: out.write(tailHtml);
0817: }
0818:
0819: private String makeHelpButton(String helpActionUrl) {
0820: return ("\t\t<a accesskey=\"h\""
0821: + " href=\""
0822: + helpActionUrl
0823: + "\" "
0824: + " title=\""
0825: + Web.escapeHtml(rb.getString("sit_help"))
0826: + "\" "
0827: + " target=\"_blank\" "
0828: + " onclick=\"openWindow('"
0829: + helpActionUrl
0830: + "', 'Help'"
0831: + ", 'resizable=yes,toolbar=no,scrollbars=yes,menubar=yes,width=800,height=600'); return false\">"
0832: + "<img src=\"/library/image/transparent.gif\""
0833: + " alt=\"" + Web.escapeHtml(rb.getString("sit_help"))
0834: + "\"" + " border=\"0\" /></a>\n");
0835: }
0836:
0837: protected void doLogin(HttpServletRequest req,
0838: HttpServletResponse res, Session session,
0839: String returnPath, boolean skipContainer)
0840: throws ToolException {
0841: try {
0842: if (basicAuth.doAuth(req, res)) {
0843: // System.err.println("BASIC Auth Request Sent to the Browser
0844: // ");
0845: return;
0846: }
0847: } catch (IOException ioex) {
0848: throw new ToolException(ioex);
0849:
0850: }
0851:
0852: // setup for the helper if needed (Note: in session, not tool session,
0853: // special for Login helper)
0854: // Note: always set this if we are passed in a return path... a blank
0855: // return path is valid... to clean up from
0856: // possible abandened previous login attempt -ggolden
0857: if (returnPath != null) {
0858: // where to go after
0859: session.setAttribute(Tool.HELPER_DONE_URL, Web.returnUrl(
0860: req, returnPath));
0861: }
0862:
0863: ActiveTool tool = ActiveToolManager
0864: .getActiveTool("sakai.login");
0865:
0866: // to skip container auth for this one, forcing things to be handled
0867: // internaly, set the "extreme" login path
0868: String loginPath = (skipContainer ? "/xlogin" : "/relogin");
0869:
0870: String context = req.getContextPath() + req.getServletPath()
0871: + loginPath;
0872: tool.help(req, res, context, loginPath);
0873: }
0874:
0875: /**
0876: * Process a logout
0877: *
0878: * @param req
0879: * Request object
0880: * @param res
0881: * Response object
0882: * @param session
0883: * Current session
0884: * @param returnPath
0885: * if not null, the path to use for the end-user browser redirect
0886: * after the logout is complete. Leave null to use the configured
0887: * logged out URL.
0888: * @throws IOException
0889: */
0890: protected void doLogout(HttpServletRequest req,
0891: HttpServletResponse res, Session session, String returnPath)
0892: throws ToolException {
0893: // where to go after
0894: if (returnPath == null) {
0895: // if no path, use the configured logged out URL
0896: String loggedOutUrl = ServerConfigurationService
0897: .getLoggedOutUrl();
0898: session.setAttribute(Tool.HELPER_DONE_URL, loggedOutUrl);
0899: } else {
0900: // if we have a path, use a return based on the request and this
0901: // path
0902: // Note: this is currently used only as "/gallery"
0903: // - we should really add a
0904: // ServerConfigurationService.getGalleryLoggedOutUrl()
0905: // and change the returnPath to a normal/gallery indicator -ggolden
0906: String loggedOutUrl = Web.returnUrl(req, returnPath);
0907: session.setAttribute(Tool.HELPER_DONE_URL, loggedOutUrl);
0908: }
0909:
0910: ActiveTool tool = ActiveToolManager
0911: .getActiveTool("sakai.login");
0912: String context = req.getContextPath() + req.getServletPath()
0913: + "/logout";
0914: tool.help(req, res, context, "/logout");
0915: }
0916:
0917: protected void doNavLogin(HttpServletRequest req,
0918: HttpServletResponse res, Session session, String siteId)
0919: throws IOException {
0920: // start the response
0921: PrintWriter out = startResponse(res, "Login", null, false);
0922:
0923: includeLogo(out, req, session, siteId);
0924: out
0925: .println("<div class=\"divColor\" id=\"tabBottom\"><br /></div></div>");
0926:
0927: // end the response
0928: endResponse(out);
0929: }
0930:
0931: protected void doNavLoginGallery(HttpServletRequest req,
0932: HttpServletResponse res, Session session, String siteId)
0933: throws IOException {
0934: // start the response
0935: PrintWriter out = startResponse(res, "Login", null, false);
0936:
0937: includeGalleryLogin(out, req, session, siteId);
0938: out
0939: .println("<div class=\"divColor\" id=\"tabBottom\"><br /></div></div>");
0940:
0941: // end the response
0942: endResponse(out);
0943: }
0944:
0945: protected void doPage(HttpServletRequest req,
0946: HttpServletResponse res, Session session, String pageId,
0947: String toolContextPath) throws ToolException, IOException {
0948: // find the page from some site
0949: SitePage page = SiteService.findPage(pageId);
0950: if (page == null) {
0951: doError(req, res, session, ERROR_WORKSITE);
0952: return;
0953: }
0954:
0955: // permission check - visit the site
0956: Site site = null;
0957: try {
0958: site = SiteService.getSiteVisit(page.getSiteId());
0959: } catch (IdUnusedException e) {
0960: doError(req, res, session, ERROR_WORKSITE);
0961: return;
0962: } catch (PermissionException e) {
0963: // if not logged in, give them a chance
0964: if (session.getUserId() == null) {
0965: doLogin(req, res, session, req.getPathInfo(), false);
0966: } else {
0967: doError(req, res, session, ERROR_WORKSITE);
0968: }
0969: return;
0970: }
0971:
0972: // form a context sensitive title
0973: String title = ServerConfigurationService
0974: .getString("ui.service")
0975: + " : " + site.getTitle() + " : " + page.getTitle();
0976:
0977: // start the response
0978: PrintWriter out = startResponse(res, title, page.getSkin(),
0979: true);
0980:
0981: // div to wrap the works
0982: String siteType = calcSiteType(site.getId());
0983: out.println("<div id=\"container\""
0984: + ((siteType != null) ? " class=\"" + siteType + "\""
0985: : "") + ">");
0986:
0987: includePage(req, res, page, toolContextPath, "contentFull");
0988: out.println("</div>");
0989:
0990: // end the response
0991: endResponse(out);
0992: }
0993:
0994: /**
0995: * Respond to data posting requests.
0996: *
0997: * @param req
0998: * The servlet request.
0999: * @param res
1000: * The servlet response.
1001: * @throws ServletException
1002: * @throws IOException
1003: */
1004: protected void doPost(HttpServletRequest req,
1005: HttpServletResponse res) throws ServletException,
1006: IOException {
1007: try {
1008: basicAuth.doLogin(req);
1009: // get the Sakai session
1010: Session session = SessionManager.getCurrentSession();
1011:
1012: // recognize what to do from the path
1013: String option = req.getPathInfo();
1014:
1015: // if missing, we have a stray post
1016: if ((option == null) || ("/".equals(option))) {
1017: doError(req, res, session, ERROR_SITE);
1018: return;
1019: }
1020:
1021: // get the parts (the first will be "")
1022: String[] parts = option.split("/");
1023:
1024: // recognize and dispatch the 'tool' option: [1] = "tool", [2] =
1025: // placement id (of a site's tool placement), rest for the tool
1026: if ((parts.length > 2) && (parts[1].equals("tool"))) {
1027: doTool(req, res, session, parts[2], req
1028: .getContextPath()
1029: + req.getServletPath()
1030: + Web.makePath(parts, 1, 3), Web.makePath(
1031: parts, 3, parts.length));
1032: } else if (enableDirect && (parts.length > 2)
1033: && (parts[1].equals("directtool"))) {
1034: // Resolve the placements of the form
1035: // /portal/tool/sakai.resources?sakai.site=~csev
1036: String toolPlacement = getPlacement(req, res, session,
1037: parts[2], false);
1038: if (toolPlacement == null) {
1039: return;
1040: }
1041: parts[2] = toolPlacement;
1042:
1043: doDirectTool(req, res, session, parts[2], req
1044: .getContextPath()
1045: + req.getServletPath()
1046: + Web.makePath(parts, 1, 3), Web.makePath(
1047: parts, 3, parts.length));
1048: }
1049:
1050: /**
1051: * Title frames were no longer used in 2.3 and are not supported in
1052: * 2.4 so we emit a WARN message here to help people with derived
1053: * classes figure out the new way.
1054: */
1055:
1056: // TODO: Remove after 2.4
1057: else if ((parts.length > 2) && (parts[1].equals("title"))) {
1058: doTitle(req, res, session, parts[2], req
1059: .getContextPath()
1060: + req.getServletPath()
1061: + Web.makePath(parts, 1, 3), Web.makePath(
1062: parts, 3, parts.length));
1063: }
1064:
1065: // recognize and dispatch the 'login' options
1066: else if ((parts.length == 2)
1067: && ((parts[1].equals("login")
1068: || (parts[1].equals("xlogin")) || (parts[1]
1069: .equals("relogin"))))) {
1070: postLogin(req, res, session, parts[1]);
1071: }
1072:
1073: // recognize help
1074: else if ((parts.length >= 2) && (parts[1].equals("help"))) {
1075: doHelp(req, res, session, req.getContextPath()
1076: + req.getServletPath()
1077: + Web.makePath(parts, 1, 2), Web.makePath(
1078: parts, 2, parts.length));
1079: }
1080:
1081: // recognize error feedback
1082: else if ((parts.length >= 2)
1083: && (parts[1].equals("error-report"))) {
1084: doErrorReport(req, res);
1085: }
1086:
1087: // handle an unrecognized request
1088: else {
1089: doError(req, res, session, ERROR_SITE);
1090: }
1091: } catch (Throwable t) {
1092: doThrowableError(req, res, t);
1093: }
1094: }
1095:
1096: protected void doPresence(HttpServletRequest req,
1097: HttpServletResponse res, Session session, String siteId,
1098: String toolContextPath, String toolPathInfo)
1099: throws ToolException, IOException {
1100: // permission check - visit the site
1101: Site site = null;
1102: try {
1103: site = SiteService.getSiteVisit(siteId);
1104: } catch (IdUnusedException e) {
1105: doError(req, res, session, ERROR_WORKSITE);
1106: return;
1107: } catch (PermissionException e) {
1108: // if not logged in, give them a chance
1109: if (session.getUserId() == null) {
1110: doLogin(req, res, session, req.getPathInfo(), false);
1111: } else {
1112: doError(req, res, session, ERROR_WORKSITE);
1113: }
1114: return;
1115: }
1116:
1117: // get the skin for the site
1118: String skin = site.getSkin();
1119:
1120: // find the tool registered for this
1121: ActiveTool tool = ActiveToolManager
1122: .getActiveTool("sakai.presence");
1123: if (tool == null) {
1124: doError(req, res, session, ERROR_WORKSITE);
1125: return;
1126: }
1127:
1128: // form a placement based on the site and the fact that this is that
1129: // site's presence...
1130: // Note: the placement is transient, but will always have the same id
1131: // and context based on the siteId
1132: org.sakaiproject.util.Placement placement = new org.sakaiproject.util.Placement(
1133: siteId + "-presence", tool.getId(), tool, null, siteId,
1134: null);
1135:
1136: forwardTool(tool, req, res, placement, skin, toolContextPath,
1137: toolPathInfo);
1138: }
1139:
1140: protected void doHelp(HttpServletRequest req,
1141: HttpServletResponse res, Session session,
1142: String toolContextPath, String toolPathInfo)
1143: throws ToolException, IOException {
1144: // permission check - none
1145:
1146: // get the detault skin
1147: String skin = ServerConfigurationService
1148: .getString("skin.default");
1149:
1150: // find the tool registered for this
1151: ActiveTool tool = ActiveToolManager.getActiveTool("sakai.help");
1152: if (tool == null) {
1153: doError(req, res, session, ERROR_WORKSITE);
1154: return;
1155: }
1156:
1157: // form a placement based on ... help TODO: is this enough?
1158: // Note: the placement is transient, but will always have the same id
1159: // and (null) context
1160: org.sakaiproject.util.Placement placement = new org.sakaiproject.util.Placement(
1161: "help", tool.getId(), tool, null, null, null);
1162:
1163: forwardTool(tool, req, res, placement, skin, toolContextPath,
1164: toolPathInfo);
1165: }
1166:
1167: protected void doErrorReport(HttpServletRequest req,
1168: HttpServletResponse res) throws ToolException, IOException {
1169: setupForward(req, res, null, null);
1170:
1171: ErrorReporter err = new ErrorReporter();
1172: err.postResponse(req, res);
1173: }
1174:
1175: protected void doErrorDone(HttpServletRequest req,
1176: HttpServletResponse res) throws ToolException, IOException {
1177: setupForward(req, res, null, null);
1178:
1179: ErrorReporter err = new ErrorReporter();
1180: err.thanksResponse(req, res);
1181: }
1182:
1183: protected void doSite(HttpServletRequest req,
1184: HttpServletResponse res, Session session, String siteId,
1185: String pageId, String toolContextPath)
1186: throws ToolException, IOException {
1187: // default site if not set
1188: if (siteId == null) {
1189: if (session.getUserId() == null) {
1190: siteId = ServerConfigurationService.getGatewaySiteId();
1191: } else {
1192: siteId = SiteService.getUserSiteId(session.getUserId());
1193: }
1194: }
1195:
1196: // if no page id, see if there was a last page visited for this site
1197: if (pageId == null) {
1198: pageId = (String) session.getAttribute(ATTR_SITE_PAGE
1199: + siteId);
1200: }
1201:
1202: // find the site, for visiting
1203: Site site = null;
1204: try {
1205: site = getSiteVisit(siteId);
1206: } catch (IdUnusedException e) {
1207: doError(req, res, session, ERROR_SITE);
1208: return;
1209: } catch (PermissionException e) {
1210: // if not logged in, give them a chance
1211: if (session.getUserId() == null) {
1212: doLogin(req, res, session, req.getPathInfo(), false);
1213: } else {
1214: doError(req, res, session, ERROR_SITE);
1215: }
1216: return;
1217: }
1218:
1219: // find the page, or use the first page if pageId not found
1220: SitePage page = site.getPage(pageId);
1221: if (page == null) {
1222: List pages = site.getOrderedPages();
1223: if (!pages.isEmpty()) {
1224: page = (SitePage) pages.get(0);
1225: }
1226: }
1227: if (page == null) {
1228: doError(req, res, session, ERROR_SITE);
1229: return;
1230: }
1231:
1232: // store the last page visited
1233: session.setAttribute(ATTR_SITE_PAGE + siteId, page.getId());
1234:
1235: // form a context sensitive title
1236: String title = ServerConfigurationService
1237: .getString("ui.service")
1238: + " : " + site.getTitle() + " : " + page.getTitle();
1239:
1240: // start the response
1241: PrintWriter out = startResponse(res, title, site.getSkin(),
1242: true);
1243:
1244: // the 'full' top area
1245: includeSiteNav(out, req, session, siteId);
1246:
1247: String siteType = calcSiteType(siteId);
1248: out.println("<div id=\"container\""
1249: + ((siteType != null) ? " class=\"" + siteType + "\""
1250: : "") + ">");
1251:
1252: includeWorksite(req, res, session, site, page, toolContextPath,
1253: "site");
1254: out.println("<div>");
1255:
1256: includeBottom(out);
1257:
1258: // end the response
1259: endResponse(out);
1260: }
1261:
1262: // Checks to see which form of tool or page placement we have. The normal
1263: // placement is
1264: // a GUID. However when the parameter sakai.site is added to the request,
1265: // the placement
1266: // can be of the form sakai.resources. This routine determines which form of
1267: // the
1268: // placement id, and if this is the second type, performs the lookup and
1269: // returns the
1270: // GUID of the placement. If we cannot resolve the pllacement, we simply
1271: // return
1272: // the passed in placement ID. If we cannot visit the site, we send the user
1273: // to login
1274: // processing and return null to the caller.
1275:
1276: protected String getPlacement(HttpServletRequest req,
1277: HttpServletResponse res, Session session,
1278: String placementId, boolean doPage) throws ToolException {
1279:
1280: String siteId = req.getParameter(PARAM_SAKAI_SITE);
1281: if (siteId == null)
1282: return placementId; // Standard placement
1283:
1284: // find the site, for visiting
1285: // Sites like the !gateway site allow visits by anonymous
1286: Site site = null;
1287: try {
1288: site = SiteService.getSiteVisit(siteId);
1289: } catch (IdUnusedException e) {
1290: return placementId; // cannot resolve placement
1291: } catch (PermissionException e) {
1292: // If we are not logged in, try again after we log in, otherwise
1293: // punt
1294: if (session.getUserId() == null) {
1295: doLogin(req, res, session, req.getPathInfo()
1296: + "?sakai.site=" + res.encodeURL(siteId), false);
1297: return null;
1298: }
1299: return placementId; // cannot resolve placement
1300: }
1301:
1302: if (site == null)
1303: return placementId;
1304: ToolConfiguration toolConfig = site
1305: .getToolForCommonId(placementId);
1306: if (toolConfig == null)
1307: return placementId;
1308:
1309: if (doPage) {
1310: return toolConfig.getPageId();
1311: } else {
1312: return toolConfig.getId();
1313: }
1314:
1315: }
1316:
1317: protected void doSiteTabs(HttpServletRequest req,
1318: HttpServletResponse res, Session session, String siteId)
1319: throws IOException {
1320: // get the site's skin
1321: String skin = SiteService.getSiteSkin(siteId);
1322:
1323: // start the response
1324: PrintWriter out = startResponse(res, "Site Navigation", skin,
1325: false);
1326:
1327: includeLogo(out, req, session, siteId);
1328: includeTabs(out, req, session, siteId, "site", false);
1329:
1330: // end the response
1331: endResponse(out);
1332: }
1333:
1334: /**
1335: * Do direct tool, takes the url, stored the destination and the target
1336: * iframe in the session constructs and outer url and when a request comes
1337: * in that matches the stored iframe it ejects the destination address
1338: *
1339: * @param req
1340: * @param res
1341: * @param session
1342: * @param placementId
1343: * @param toolContextPath
1344: * @param toolPathInfo
1345: * @param placementId
1346: * @throws ToolException
1347: * @throws IOException
1348: */
1349: protected void doDirectTool(HttpServletRequest req,
1350: HttpServletResponse res, Session session,
1351: String placementId, String toolContextPath,
1352: String toolPathInfo) throws ToolException, IOException {
1353: if (redirectIfLoggedOut(res))
1354: return;
1355:
1356: // find the tool from some site
1357: ToolConfiguration siteTool = SiteService.findTool(placementId);
1358: if (siteTool == null) {
1359: doError(req, res, session, ERROR_WORKSITE);
1360: return;
1361: }
1362:
1363: // Reset the tool state if requested
1364: if (portalService.isResetRequested(req)) {
1365: Session s = SessionManager.getCurrentSession();
1366: ToolSession ts = s.getToolSession(placementId);
1367: ts.clearAttributes();
1368: }
1369:
1370: // find the tool registered for this
1371: ActiveTool tool = ActiveToolManager.getActiveTool(siteTool
1372: .getToolId());
1373: if (tool == null) {
1374: doError(req, res, session, ERROR_WORKSITE);
1375: return;
1376: }
1377:
1378: // permission check - visit the site (unless the tool is configured to
1379: // bypass)
1380: if (tool.getAccessSecurity() == Tool.AccessSecurity.PORTAL) {
1381: Site site = null;
1382: try {
1383: site = SiteService.getSiteVisit(siteTool.getSiteId());
1384: } catch (IdUnusedException e) {
1385: doError(req, res, session, ERROR_WORKSITE);
1386: return;
1387: } catch (PermissionException e) {
1388: // if not logged in, give them a chance
1389: if (session.getUserId() == null) {
1390: // let the tool do the the work (forward)
1391: StoredState ss = portalService.newStoredState(
1392: "directtool", "tool");
1393: ss.setRequest(req);
1394: ss.setPlacement(siteTool);
1395: ss.setToolContextPath(toolContextPath);
1396: ss.setToolPathInfo(toolPathInfo);
1397: ss.setSkin(siteTool.getSkin());
1398: portalService.setStoredState(ss);
1399:
1400: doLogin(req, res, session,
1401: getPortalPageUrl(siteTool), false);
1402: } else {
1403: doError(req, res, session, ERROR_WORKSITE);
1404: }
1405: return;
1406: }
1407: }
1408: // let the tool do the the work (forward)
1409: StoredState ss = portalService.newStoredState("directtool",
1410: "tool");
1411: ss.setRequest(req);
1412: ss.setPlacement(siteTool);
1413: ss.setToolContextPath(toolContextPath);
1414: ss.setToolPathInfo(toolPathInfo);
1415: ss.setSkin(siteTool.getSkin());
1416: portalService.setStoredState(ss);
1417:
1418: forwardPortal(tool, req, res, siteTool, siteTool.getSkin(),
1419: toolContextPath, toolPathInfo);
1420:
1421: }
1422:
1423: protected void doTool(HttpServletRequest req,
1424: HttpServletResponse res, Session session,
1425: String placementId, String toolContextPath,
1426: String toolPathInfo) throws ToolException, IOException {
1427: if (redirectIfLoggedOut(res))
1428: return;
1429:
1430: // find the tool from some site
1431: ToolConfiguration siteTool = SiteService.findTool(placementId);
1432: if (siteTool == null) {
1433: doError(req, res, session, ERROR_WORKSITE);
1434: return;
1435: }
1436:
1437: // Reset the tool state if requested
1438: if (portalService.isResetRequested(req)) {
1439: Session s = SessionManager.getCurrentSession();
1440: ToolSession ts = s.getToolSession(placementId);
1441: ts.clearAttributes();
1442: }
1443:
1444: // find the tool registered for this
1445: ActiveTool tool = ActiveToolManager.getActiveTool(siteTool
1446: .getToolId());
1447: if (tool == null) {
1448: doError(req, res, session, ERROR_WORKSITE);
1449: return;
1450: }
1451:
1452: // permission check - visit the site (unless the tool is configured to
1453: // bypass)
1454: if (tool.getAccessSecurity() == Tool.AccessSecurity.PORTAL) {
1455: Site site = null;
1456: try {
1457: site = SiteService.getSiteVisit(siteTool.getSiteId());
1458: } catch (IdUnusedException e) {
1459: doError(req, res, session, ERROR_WORKSITE);
1460: return;
1461: } catch (PermissionException e) {
1462: // if not logged in, give them a chance
1463: if (session.getUserId() == null) {
1464: doLogin(req, res, session, req.getPathInfo(), false);
1465: } else {
1466: doError(req, res, session, ERROR_WORKSITE);
1467: }
1468: return;
1469: }
1470: }
1471:
1472: forwardTool(tool, req, res, siteTool, siteTool.getSkin(),
1473: toolContextPath, toolPathInfo);
1474: }
1475:
1476: protected void setupForward(HttpServletRequest req,
1477: HttpServletResponse res, Placement p, String skin)
1478: throws ToolException {
1479: // setup html information that the tool might need (skin, body on load,
1480: // js includes, etc).
1481: if (skin == null || skin.length() == 0)
1482: skin = ServerConfigurationService.getString("skin.default");
1483: String skinRepo = ServerConfigurationService
1484: .getString("skin.repo");
1485: String headCssToolBase = "<link href=\""
1486: + skinRepo
1487: + "/tool_base.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />\n";
1488: String headCssToolSkin = "<link href=\""
1489: + skinRepo
1490: + "/"
1491: + skin
1492: + "/tool.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />\n";
1493: String headCss = headCssToolBase + headCssToolSkin;
1494: String headJs = "<script type=\"text/javascript\" language=\"JavaScript\" src=\"/library/js/headscripts.js\"></script>\n";
1495: String head = headCss + headJs;
1496: StringBuilder bodyonload = new StringBuilder();
1497: if (p != null) {
1498: String element = Web.escapeJavascript("Main" + p.getId());
1499: bodyonload.append("setMainFrameHeight('" + element + "');");
1500: }
1501: bodyonload.append("setFocus(focus_path);");
1502:
1503: // to force all non-legacy tools to use the standard css
1504: // to help in transition (needs corresponding entry in properties)
1505: // if
1506: // ("true".equals(ServerConfigurationService.getString("skin.force")))
1507: // {
1508: // headJs = headJs + headCss;
1509: // }
1510:
1511: req.setAttribute("sakai.html.head", head);
1512: req.setAttribute("sakai.html.head.css", headCss);
1513: req.setAttribute("sakai.html.head.css.base", headCssToolBase);
1514: req.setAttribute("sakai.html.head.css.skin", headCssToolSkin);
1515: req.setAttribute("sakai.html.head.js", headJs);
1516: req.setAttribute("sakai.html.body.onload", bodyonload
1517: .toString());
1518: }
1519:
1520: /**
1521: * Forward to the tool - but first setup JavaScript/CSS etc that the tool
1522: * will render
1523: */
1524: protected void forwardTool(ActiveTool tool, HttpServletRequest req,
1525: HttpServletResponse res, Placement p, String skin,
1526: String toolContextPath, String toolPathInfo)
1527: throws ToolException {
1528:
1529: // if there is a stored request state, and path, extract that from the
1530: // session and
1531: // reinstance it
1532:
1533: // let the tool do the the work (forward)
1534: if (enableDirect) {
1535: StoredState ss = portalService.getStoredState();
1536: if (ss == null
1537: || !toolContextPath.equals(ss.getToolContextPath())) {
1538: setupForward(req, res, p, skin);
1539: req.setAttribute(ToolURL.MANAGER,
1540: new ToolURLManagerImpl(res));
1541: tool
1542: .forward(req, res, p, toolContextPath,
1543: toolPathInfo);
1544: } else {
1545: HttpServletRequest sreq = ss.getRequest(req);
1546: Placement splacement = ss.getPlacement();
1547: String stoolContext = ss.getToolContextPath();
1548: String stoolPathInfo = ss.getToolPathInfo();
1549: ActiveTool stool = ActiveToolManager.getActiveTool(p
1550: .getToolId());
1551: String sskin = ss.getSkin();
1552: setupForward(sreq, res, splacement, sskin);
1553: req.setAttribute(ToolURL.MANAGER,
1554: new ToolURLManagerImpl(res));
1555: stool.forward(sreq, res, splacement, stoolContext,
1556: stoolPathInfo);
1557: // This is correct as we have checked the context path of the
1558: // target
1559: portalService.setStoredState(null);
1560: }
1561: } else {
1562: setupForward(req, res, p, skin);
1563: req.setAttribute(ToolURL.MANAGER, new ToolURLManagerImpl(
1564: res));
1565: tool.forward(req, res, p, toolContextPath, toolPathInfo);
1566: }
1567:
1568: }
1569:
1570: protected void forwardPortal(ActiveTool tool,
1571: HttpServletRequest req, HttpServletResponse res,
1572: ToolConfiguration p, String skin, String toolContextPath,
1573: String toolPathInfo) throws ToolException, IOException {
1574:
1575: // if there is a stored request state, and path, extract that from the
1576: // session and
1577: // reinstance it
1578:
1579: // generate the forward to the tool page placement
1580: String portalPlacementUrl = "/portal" + getPortalPageUrl(p);
1581: res.sendRedirect(portalPlacementUrl);
1582: return;
1583:
1584: }
1585:
1586: protected String getPortalPageUrl(ToolConfiguration p) {
1587: return "/site/" + p.getSiteId() + "/page/" + p.getPageId();
1588: }
1589:
1590: protected void doWorksite(HttpServletRequest req,
1591: HttpServletResponse res, Session session, String siteId,
1592: String pageId, String toolContextPath)
1593: throws ToolException, IOException {
1594: // if no page id, see if there was a last page visited for this site
1595: if (pageId == null) {
1596: pageId = (String) session.getAttribute(ATTR_SITE_PAGE
1597: + siteId);
1598: }
1599:
1600: // find the site, for visiting
1601: Site site = null;
1602: try {
1603: site = getSiteVisit(siteId);
1604: } catch (IdUnusedException e) {
1605: doError(req, res, session, ERROR_WORKSITE);
1606: return;
1607: } catch (PermissionException e) {
1608: // if not logged in, give them a chance
1609: if (session.getUserId() == null) {
1610: doLogin(req, res, session, req.getPathInfo(), false);
1611: } else {
1612: doError(req, res, session, ERROR_WORKSITE);
1613: }
1614: return;
1615: }
1616:
1617: // find the page, or use the first page if pageId not found
1618: SitePage page = site.getPage(pageId);
1619: if (page == null) {
1620: List pages = site.getOrderedPages();
1621: if (!pages.isEmpty()) {
1622: page = (SitePage) pages.get(0);
1623: }
1624: }
1625: if (page == null) {
1626: doError(req, res, session, ERROR_WORKSITE);
1627: return;
1628: }
1629:
1630: // store the last page visited
1631: session.setAttribute(ATTR_SITE_PAGE + siteId, page.getId());
1632:
1633: // form a context sensitive title
1634: String title = ServerConfigurationService
1635: .getString("ui.service")
1636: + " : " + site.getTitle() + " : " + page.getTitle();
1637:
1638: // start the response
1639: PrintWriter out = startResponse(res, title, site.getSkin(),
1640: true);
1641:
1642: String siteType = calcSiteType(siteId);
1643: out.println("<div id=\"container\""
1644: + ((siteType != null) ? " class=\"" + siteType + "\""
1645: : "") + ">");
1646:
1647: includeWorksite(req, res, session, site, page, toolContextPath,
1648: "worksite");
1649: out.println("<div>");
1650:
1651: // end the response
1652: endResponse(out);
1653: }
1654:
1655: protected void endResponse(PrintWriter out) {
1656: out.println("</body></html>");
1657: }
1658:
1659: protected String getScriptPath() {
1660: String libPath = "/library";
1661: return libPath + "/js/";
1662: }
1663:
1664: /**
1665: * Access the Servlet's information display.
1666: *
1667: * @return servlet information.
1668: */
1669: public String getServletInfo() {
1670: return "Sakai Charon Portal";
1671: }
1672:
1673: protected void includeBottom(PrintWriter out) {
1674: String copyright = ServerConfigurationService
1675: .getString("bottom.copyrighttext");
1676: String service = ServerConfigurationService.getString(
1677: "ui.service", "Sakai");
1678: String serviceVersion = ServerConfigurationService.getString(
1679: "version.service", "?");
1680: String sakaiVersion = ServerConfigurationService.getString(
1681: "version.sakai", "?");
1682: String server = ServerConfigurationService.getServerId();
1683: String[] bottomNav = ServerConfigurationService
1684: .getStrings("bottomnav");
1685: String[] poweredByUrl = ServerConfigurationService
1686: .getStrings("powered.url");
1687: String[] poweredByImage = ServerConfigurationService
1688: .getStrings("powered.img");
1689: String[] poweredByAltText = ServerConfigurationService
1690: .getStrings("powered.alt");
1691:
1692: out.println("<div id=\"footer\">");
1693: out.println(" <div class=\"footerExtNav\" align=\"center\">");
1694: out.println(" |");
1695:
1696: if ((bottomNav != null) && (bottomNav.length > 0)) {
1697: for (int i = 0; i < bottomNav.length; i++) {
1698: out.println(" " + bottomNav[i] + " | ");
1699: }
1700: }
1701:
1702: out.println(" </div>");
1703: out.println(" <div id=\"footerInfo\">");
1704: if ((poweredByUrl != null) && (poweredByImage != null)
1705: && (poweredByAltText != null)
1706: && (poweredByUrl.length == poweredByImage.length)
1707: && (poweredByUrl.length == poweredByAltText.length)) {
1708: for (int i = 0; i < poweredByUrl.length; i++) {
1709: out.println(" <span class=\"skip\">"
1710: + Web
1711: .escapeHtml(rb
1712: .getString("site_newwindow"))
1713: + "</span> <a href=\"" + poweredByUrl[i]
1714: + "\" target=\"_blank\">"
1715: + "<img border=\"0\" src=\""
1716: + poweredByImage[i] + "\" alt=\""
1717: + poweredByAltText[i] + "\" /></a>");
1718: }
1719: } else {
1720: out
1721: .println(" <span class=\"skip\">"
1722: + Web.escapeHtml(rb
1723: .getString("site_newwindow"))
1724: + "</span><a href=\"http://sakaiproject.org\" target=\"_blank\">"
1725: + "<img border=\"0\" src=\"/library/image/sakai_powered.gif\" alt=\"Powered by Sakai\" /></a>");
1726: }
1727: out.println(" </div>");
1728: out.println(" <div class=\"sakaiCopyrightInfo\">" + copyright
1729: + "<br />");
1730: out.println(" " + service + " - " + serviceVersion
1731: + " - Sakai " + sakaiVersion + " - Server \"" + server
1732: + "\"</div>");
1733: out.println(" </div>");
1734: out.println("</div>");
1735: out.println("</div>");
1736: out.println("</div>");
1737: out.println("</div>");
1738: }
1739:
1740: protected void includeGalleryLogin(PrintWriter out,
1741: HttpServletRequest req, Session session, String siteId)
1742: throws IOException {
1743: out.println("<div class=\"siteNavBlock\">");
1744: out
1745: .println("<table class=\"mast-head\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" width=\"100%\">");
1746: out.println(" <tr>");
1747: out.println(" <td class=\"right mast-head-r right\">");
1748: this .includeLogin(out, req, session);
1749: out.println(" </td>");
1750: out.println(" </tr>");
1751: out.println("</table>");
1752: }
1753:
1754: protected void includeGalleryNav(PrintWriter out,
1755: HttpServletRequest req, Session session, String siteId) {
1756: boolean loggedIn = session.getUserId() != null;
1757: boolean topLogin = ServerConfigurationService.getBoolean(
1758: "top.login", true);
1759:
1760: String siteNavUrl = null;
1761:
1762: if (loggedIn) {
1763: siteNavUrl = Web.returnUrl(req, "/gallery_tabs/"
1764: + Web.escapeUrl(siteId));
1765: } else {
1766: siteNavUrl = Web.returnUrl(req, "/nav_login_gallery/"
1767: + Web.escapeUrl(siteId));
1768: }
1769:
1770: // outer blocks and jump-to links
1771: out.println(" <div id=\"portalOuterContainer\">");
1772: out.println(" <div id=\"portalContainer\">");
1773: out.println("<div id=\"skipNav\">");
1774: String accessibilityURL = ServerConfigurationService
1775: .getString("accessibility.url");
1776: if (accessibilityURL != null && accessibilityURL != "") {
1777: out.println("<a href=\"" + accessibilityURL
1778: + "\" class=\"skip\" title=\""
1779: + Web.escapeHtml(rb.getString("sit_accessibility"))
1780: + "\" accesskey=\"0\">"
1781: + Web.escapeHtml(rb.getString("sit_accessibility"))
1782: + "</a>");
1783: }
1784: out.println(" <a href=\"#tocontent\" class=\"skip\" title=\""
1785: + Web.escapeHtml(rb.getString("sit_jumpcontent"))
1786: + "\" accesskey=\"c\">"
1787: + Web.escapeHtml(rb.getString("sit_jumpcontent"))
1788: + "</a>");
1789: out.println(" <a href=\"#totoolmenu\" class=\"skip\" title=\""
1790: + Web.escapeHtml(rb.getString("sit_jumptools"))
1791: + "\" accesskey=\"l\">"
1792: + Web.escapeHtml(rb.getString("sit_jumptools"))
1793: + "</a>");
1794: out.println(" <a href=\"#sitetabs\" class=\"skip\" title=\""
1795: + Web.escapeHtml(rb.getString("sit_jumpworksite"))
1796: + "\" accesskey=\"w\">"
1797: + Web.escapeHtml(rb.getString("sit_jumpworksite"))
1798: + "</a>");
1799: out.println("</div>");
1800: if (loggedIn) {
1801: out.println("<div id=\"headerMax\">");
1802: } else {
1803: out.println("<div id=\"headerMin\">");
1804: }
1805:
1806: try {
1807: if (loggedIn) {
1808: includeTabs(out, req, session, siteId, "gallery", false);
1809: } else {
1810: includeGalleryLogin(out, req, session, siteId);
1811: out
1812: .println("<div class=\"divColor\" id=\"tabBottom\"><br /></div></div>");
1813: }
1814: } catch (Exception any) {
1815: }
1816:
1817: out.println("</div>");
1818: }
1819:
1820: protected void includeLogo(PrintWriter out, HttpServletRequest req,
1821: Session session, String siteId) throws IOException {
1822: String skin = SiteService.getSiteSkin(siteId);
1823: if (skin == null) {
1824: skin = ServerConfigurationService.getString("skin.default");
1825: }
1826: String skinRepo = ServerConfigurationService
1827: .getString("skin.repo");
1828:
1829: String logo = skinRepo + "/" + skin + "/images/logo_inst.gif";
1830: String banner = skinRepo + "/" + skin
1831: + "/images/banner_inst.gif";
1832:
1833: String siteType = calcSiteType(siteId);
1834: String cssClass = (siteType != null) ? siteType
1835: : "undeterminedSiteType";
1836: out.println("<div id=\"siteNavWrapper\" class=\"" + cssClass
1837: + "\">");
1838: out.println("<div id=\"mastHead\">");
1839: out.println(" <div id=\"mastLogo\">");
1840: out.println(" <img title=\"Logo\" alt=\"Logo\" src=\"" + logo
1841: + "\" />");
1842: out.println(" </div>");
1843: out.println(" <div id=\"mastBanner\">");
1844: out.println(" <img title=\"Banner\" alt=\"Banner\" src=\""
1845: + banner + "\" />");
1846: out.println(" </div>");
1847: out.println(" <div id=\"mastLogin\">");
1848: includeLogin(out, req, session);
1849: out.println(" </div>");
1850: out.println("</div>");
1851: }
1852:
1853: protected void includeLogin(PrintWriter out,
1854: HttpServletRequest req, Session session) {
1855: // for the main login/out link
1856: String logInOutUrl = Web.serverUrl(req);
1857: String message = null;
1858: String image1 = null;
1859:
1860: // for a possible second link
1861: String logInOutUrl2 = null;
1862: String message2 = null;
1863: String image2 = null;
1864:
1865: // check for the top.login (where the login fields are present instead
1866: // of a login link, but ignore it if container.login is set
1867: boolean topLogin = Boolean.TRUE.toString().equalsIgnoreCase(
1868: ServerConfigurationService.getString("top.login"));
1869: boolean containerLogin = Boolean.TRUE.toString()
1870: .equalsIgnoreCase(
1871: ServerConfigurationService
1872: .getString("container.login"));
1873: if (containerLogin)
1874: topLogin = false;
1875:
1876: // if not logged in they get login
1877: if (session.getUserId() == null) {
1878: // we don't need any of this if we are doing top login
1879: if (!topLogin) {
1880: logInOutUrl += ServerConfigurationService
1881: .getString("portalPath")
1882: + "/login";
1883:
1884: // let the login url be overridden by configuration
1885: String overrideLoginUrl = StringUtil
1886: .trimToNull(ServerConfigurationService
1887: .getString("login.url"));
1888: if (overrideLoginUrl != null)
1889: logInOutUrl = overrideLoginUrl;
1890:
1891: // check for a login text override
1892: message = StringUtil
1893: .trimToNull(ServerConfigurationService
1894: .getString("login.text"));
1895: if (message == null)
1896: message = rb.getString("log.login");
1897:
1898: // check for an image for the login
1899: image1 = StringUtil
1900: .trimToNull(ServerConfigurationService
1901: .getString("login.icon"));
1902:
1903: // check for a possible second, xlogin link
1904: if (Boolean.TRUE.toString().equalsIgnoreCase(
1905: ServerConfigurationService
1906: .getString("xlogin.enabled"))) {
1907: // get the text and image as configured
1908: message2 = StringUtil
1909: .trimToNull(ServerConfigurationService
1910: .getString("xlogin.text"));
1911: image2 = StringUtil
1912: .trimToNull(ServerConfigurationService
1913: .getString("xlogin.icon"));
1914: logInOutUrl2 = ServerConfigurationService
1915: .getString("portalPath")
1916: + "/xlogin";
1917: }
1918: }
1919: }
1920:
1921: // if logged in they get logout
1922: else {
1923: logInOutUrl += ServerConfigurationService
1924: .getString("portalPath")
1925: + "/logout";
1926:
1927: // check for a logout text override
1928: message = StringUtil.trimToNull(ServerConfigurationService
1929: .getString("logout.text"));
1930: if (message == null)
1931: message = rb.getString("sit_log");
1932:
1933: // check for an image for the logout
1934: image1 = StringUtil.trimToNull(ServerConfigurationService
1935: .getString("logout.icon"));
1936:
1937: // since we are doing logout, cancel top.login
1938: topLogin = false;
1939: }
1940:
1941: // put out the links version
1942: if (!topLogin) {
1943: out.println("<div id=\"loginLinks\">");
1944: out.println(" <a href=\""
1945: + logInOutUrl
1946: + "\" target=\"_parent\" title=\""
1947: + message
1948: + "\">"
1949: + ((image1 == null) ? message : "<img src=\""
1950: + image1 + "\"/>") + "</a>");
1951: if (logInOutUrl2 != null) {
1952: out.println(" <a href=\""
1953: + logInOutUrl2
1954: + "\" target=\"_parent\" title=\""
1955: + message2
1956: + "\">"
1957: + ((image2 == null) ? message2 : "<img alt=\""
1958: + message2 + "\" src=\"" + image2
1959: + "\"/>") + "</a>");
1960: }
1961: out.println("</div>");
1962: }
1963:
1964: // else put out the fields that will send to the login interface
1965: else {
1966: // find the login tool
1967: Tool loginTool = ToolManager.getTool("sakai.login");
1968: String eidWording = null;
1969: String pwWording = null;
1970: eidWording = StringUtil.trimToNull(rb
1971: .getString("log.userid"));
1972: pwWording = StringUtil.trimToNull(rb.getString("log.pass"));
1973:
1974: if (eidWording == null)
1975: eidWording = "eid";
1976: if (pwWording == null)
1977: pwWording = "pw";
1978: String loginWording = rb.getString("log.login");
1979:
1980: out
1981: .println("<form id=\"loginForm\" method=\"post\" action=\""
1982: + ServerConfigurationService
1983: .getString("portalPath")
1984: + "/xlogin\" enctype=\"application/x-www-form-urlencoded\" target=\"_parent\">");
1985: out
1986: .println("<label for=\"eid\">"
1987: + eidWording
1988: + "</label><input name=\"eid\" id=\"eid\" type=\"text\" />");
1989: out
1990: .println("<label for=\"pw\">"
1991: + pwWording
1992: + "</label><input name=\"pw\" type=\"password\" id=\"pw\" />");
1993: out
1994: .println("<input name=\"submit\" type=\"submit\" id=\"submit\" value=\""
1995: + loginWording + "\" /> </form>");
1996:
1997: out
1998: .println("<script type=\"text/javascript\" language=\"JavaScript\">");
1999: out.println("document.forms[0].eid.focus();");
2000: out.println("</script>");
2001:
2002: // setup for the redirect after login
2003: session.setAttribute(Tool.HELPER_DONE_URL,
2004: ServerConfigurationService.getPortalUrl());
2005: }
2006: }
2007:
2008: protected void includePage(HttpServletRequest req,
2009: HttpServletResponse res, SitePage page,
2010: String toolContextPath, String wrapperClass)
2011: throws IOException {
2012: PrintWriter out = res.getWriter();
2013: // divs to wrap the tools
2014:
2015: // divs to wrap the tools
2016: out.println("<div id=\"" + wrapperClass + "\">");
2017:
2018: // get the tools on this first column of page
2019: if (page.getLayout() == SitePage.LAYOUT_DOUBLE_COL) {
2020: out.println("<div id=\"col1of2\">");
2021: } else {
2022: out.println("<div id=\"col1\">");
2023: }
2024:
2025: Site site = null;
2026: try {
2027: site = SiteService.getSite(page.getSiteId());
2028: } catch (Exception ignoreMe) {
2029: // Non fatal - just assume null
2030: if (M_log.isTraceEnabled())
2031: M_log.trace("includePage unable to find site for page "
2032: + page.getId());
2033: }
2034:
2035: List tools = page.getTools(0);
2036: for (Iterator i = tools.iterator(); i.hasNext();) {
2037: ToolConfiguration placement = (ToolConfiguration) i.next();
2038:
2039: if (site != null) {
2040: boolean this Tool = allowTool(site, placement);
2041: // System.out.println(" Allow Tool Display -" +
2042: // placement.getTitle() + " retval = " + thisTool);
2043: if (!this Tool)
2044: continue; // Skip this tool if not allowed
2045: }
2046:
2047: // for this tool invocation, form the servlet context and path info
2048: String contextPath = ServerConfigurationService
2049: .getToolUrl()
2050: + "/" + Web.escapeUrl(placement.getId());
2051: String pathInfo = null;
2052:
2053: // invoke the tool
2054: includeTool(req, res, placement);
2055: }
2056: out.println("</div>");
2057:
2058: // do the second column if needed
2059: if (page.getLayout() == SitePage.LAYOUT_DOUBLE_COL) {
2060: out.println("<div id=\"col2of2\">");
2061: tools = page.getTools(1);
2062: for (Iterator i = tools.iterator(); i.hasNext();) {
2063: ToolConfiguration placement = (ToolConfiguration) i
2064: .next();
2065:
2066: // for this tool invocation, form the servlet context and path
2067: // info
2068: String contextPath = ServerConfigurationService
2069: .getToolUrl()
2070: + "/" + Web.escapeUrl(placement.getId());
2071: String pathInfo = null;
2072:
2073: // invoke the tool
2074: includeTool(req, res, placement);
2075: }
2076: out.println("</div>");
2077: }
2078:
2079: out.println("</div>");
2080: }
2081:
2082: protected boolean allowTool(Site site, Placement placement) {
2083: if (placement == null || site == null)
2084: return true; // No way to render
2085: // an opinion
2086:
2087: boolean retval = true;
2088:
2089: String TOOL_CFG_FUNCTIONS = "functions.require";
2090: Properties roleConfig = placement.getConfig();
2091: String roleList = roleConfig.getProperty(TOOL_CFG_FUNCTIONS);
2092:
2093: // allow by default, when no config keys are present
2094: if (roleList != null && roleList.trim().length() > 0) {
2095: String[] result = roleConfig
2096: .getProperty(TOOL_CFG_FUNCTIONS).split("\\,");
2097: for (int x = 0; x < result.length; x++) {
2098: if (!SecurityService.unlock(result[x].trim(), site
2099: .getReference()))
2100: retval = false;
2101: }
2102: }
2103: return retval;
2104: }
2105:
2106: protected void includePageNav(HttpServletRequest req,
2107: HttpServletResponse res, Session session, Site site,
2108: SitePage page, String toolContextPath, String portalPrefix)
2109: throws IOException {
2110: PrintWriter out = res.getWriter();
2111: // If we have turned on auto-state reset on navigation, we generate the
2112: // "site-reset" "worksite-reset" and "gallery-reset" urls
2113: if ("true".equals(ServerConfigurationService
2114: .getString(CONFIG_AUTO_RESET))) {
2115: portalPrefix = portalPrefix + "-reset";
2116: }
2117:
2118: String pageUrl = Web.returnUrl(req, "/" + portalPrefix + "/"
2119: + Web.escapeUrl(getSiteEffectiveId(site)) + "/page/");
2120: String pagePopupUrl = Web.returnUrl(req, "/page/");
2121: boolean showPresence = ServerConfigurationService.getBoolean(
2122: "display.users.present", true);
2123: boolean showHelp = ServerConfigurationService.getBoolean(
2124: "display.help.menu", true);
2125: boolean loggedIn = session.getUserId() != null;
2126: String iconUrl = site.getIconUrlFull();
2127: boolean published = site.isPublished();
2128: String type = site.getType();
2129:
2130: out.println("<div class=\"divColor\" id=\"toolMenuWrap\">");
2131: out.println(" <div id=\"worksiteLogo\">");
2132: if (!published) {
2133: out.println("<p id=\"siteStatus\">" + "unpublished site"
2134: + "</p>");
2135: }
2136: if (type != null) {
2137: if (type.equals("project")) {
2138: out.println("<p id=\"siteType\">" + type + "</p>");
2139: }
2140: }
2141: if (iconUrl != null) {
2142: out
2143: .println(" <img src=\"" + iconUrl
2144: + "\" border=\"0\" />");
2145: }
2146: out.println(" </div>");
2147:
2148: // target of "jump to tools" link, header
2149: out
2150: .println(" <a id=\"totoolmenu\" class=\"skip\" name=\"totoolmenu\"></a>");
2151: out.println(" <h1 class=\"skip\">"
2152: + Web.escapeHtml(rb.getString("sit_toolshead"))
2153: + "</h1>");
2154:
2155: out.println(" <div id=\"toolMenu\">");
2156: out.println(" <ul>");
2157:
2158: // order the pages based on their tools and the tool order for the site
2159: // type
2160: List pages = site.getOrderedPages();
2161:
2162: // gsilver - counter for tool accesskey attributes of <a>
2163: // int count = 0;
2164:
2165: for (Iterator i = pages.iterator(); i.hasNext();) {
2166: SitePage p = (SitePage) i.next();
2167:
2168: // check if current user has permission to see page
2169: // will draw page button if it have permission to see at least one
2170: // tool
2171: List pTools = p.getTools();
2172: Iterator iPt = pTools.iterator();
2173:
2174: boolean allowPage = false;
2175: while (iPt.hasNext()) {
2176: ToolConfiguration placement = (ToolConfiguration) iPt
2177: .next();
2178:
2179: boolean this Tool = allowTool(site, placement);
2180: if (this Tool)
2181: allowPage = true;
2182: // System.out.println(" Allow Tool -" + tool.getTitle() + "
2183: // retval = " + thisTool + " page=" + allowPage);
2184: }
2185:
2186: if (!allowPage)
2187: continue;
2188:
2189: boolean current = (p.getId().equals(page.getId()) && !p
2190: .isPopUp());
2191:
2192: if (current) {
2193: out.print(" <li class=\"selectedTool\"><a ");
2194: } else {
2195: out.print(" <li><a ");
2196: }
2197:
2198: // removing accesskeys from tool menu
2199: // if (count < 10)
2200: // {
2201: // out.print("accesskey=\"" + count + "\" ");
2202: // }
2203: if (current) {
2204: out.print("class=\"selected\" ");
2205: }
2206: out.print("href=\"");
2207: if (current) {
2208: out.print("#");
2209: } else if (p.isPopUp()) {
2210: out
2211: .print("javascript:;\" "
2212: + "onclick=\"window.open('"
2213: + pagePopupUrl
2214: + Web.escapeUrl(p.getId())
2215: + "'"
2216: + ",'"
2217: + Web.escapeJavascript(p.getTitle())
2218: + "','resizable=yes,toolbar=no,scrollbars=yes, width=800,height=600')");
2219: } else {
2220: String pagerefUrl = pageUrl + Web.escapeUrl(p.getId());
2221: out.print(pagerefUrl);
2222: }
2223: out.println("\"><span>" + Web.escapeHtml(p.getTitle())
2224: + "</span></a></li>");
2225:
2226: // count++;
2227: }
2228:
2229: if (showHelp) {
2230: String helpUrl = ServerConfigurationService
2231: .getHelpUrl(null);
2232: out.println(" <li>");
2233:
2234: // help gets its own accesskey - 6
2235: out
2236: .println(" <a accesskey=\"6\" href=\""
2237: + helpUrl
2238: + "\" target=\"_blank\" "
2239: + "onclick=\"openWindow('"
2240: + helpUrl
2241: + "', 'Help', 'resizable=yes,toolbar=no,scrollbars=yes,menubar=yes,width=800,height=600'); return false\">"
2242: + "<span>" + rb.getString("sit_help")
2243: + "</span></a>");
2244:
2245: out.println(" </li>");
2246: }
2247:
2248: out.println(" </ul>");
2249: out.println(" </div>");
2250: if (showPresence && loggedIn) {
2251: String presenceUrl = Web.returnUrl(req, "/presence/"
2252: + Web.escapeUrl(site.getId()));
2253: out.println(" <div id=\"presenceWrapper\">");
2254: out.println(" <div id=\"presenceTitle\">");
2255: out.println(Web.escapeHtml(rb
2256: .getString("sit_presencetitle")));
2257: out.println(" </div>");
2258: out.println(" <iframe ");
2259: out.println(" name=\"presenceIframe\"");
2260: out.println(" id=\"presenceIframe\"");
2261: out
2262: .println(" title=\""
2263: + Web
2264: .escapeHtml(rb
2265: .getString("sit_presenceiframetit"))
2266: + "\"");
2267: out.println(" frameborder=\"0\"");
2268: out.println(" marginwidth=\"0\"");
2269: out.println(" marginheight=\"0\"");
2270: out.println(" scrolling=\"auto\"");
2271: out.println(" src=\"" + presenceUrl + "\"");
2272: out.println(" >");
2273: out.println(" </iframe>");
2274: out.println(" </div>");
2275: }
2276: out.println("</div>");
2277:
2278: // target of "jump to content" link and header for content
2279:
2280: out.println(" <h1 class=\"skip\">"
2281: + Web.escapeHtml(rb.getString("sit_contentshead"))
2282: + "</h1>");
2283: out
2284: .println(" <a id=\"tocontent\" class=\"skip\" name=\"tocontent\"></a>");
2285:
2286: }
2287:
2288: protected void includeSiteNav(PrintWriter out,
2289: HttpServletRequest req, Session session, String siteId) {
2290: boolean loggedIn = session.getUserId() != null;
2291: boolean topLogin = ServerConfigurationService.getBoolean(
2292: "top.login", true);
2293:
2294: String siteNavUrl = null;
2295: int height = 0;
2296: String siteNavClass = null;
2297:
2298: if (loggedIn) {
2299: siteNavUrl = Web.returnUrl(req, "/site_tabs/"
2300: + Web.escapeUrl(siteId));
2301: height = 104;
2302: siteNavClass = "sitenav-max";
2303: } else {
2304: siteNavUrl = Web.returnUrl(req, "/nav_login/"
2305: + Web.escapeUrl(siteId));
2306: height = 80;
2307: siteNavClass = "sitenav-log";
2308: }
2309:
2310: // outer blocks and jump to links
2311: out.println(" <div id=\"portalOuterContainer\">");
2312: out.println(" <div id=\"portalContainer\">");
2313: out.println("<div id=\"skipNav\">");
2314:
2315: String accessibilityURL = ServerConfigurationService
2316: .getString("accessibility.url");
2317: if (accessibilityURL != null && accessibilityURL != "") {
2318: out.println("<a href=\"" + accessibilityURL
2319: + "\" class=\"skip\" title=\""
2320: + Web.escapeHtml(rb.getString("sit_accessibility"))
2321: + "\" accesskey=\"0\">"
2322: + Web.escapeHtml(rb.getString("sit_accessibility"))
2323: + "</a>");
2324: }
2325: out.println("<a href=\"#tocontent\" class=\"skip\" title=\""
2326: + Web.escapeHtml(rb.getString("sit_jumpcontent"))
2327: + "\" accesskey=\"c\">"
2328: + Web.escapeHtml(rb.getString("sit_jumpcontent"))
2329: + "</a>");
2330: out.println("<a href=\"#totoolmenu\" class=\"skip\" title=\""
2331: + Web.escapeHtml(rb.getString("sit_jumptools"))
2332: + "\" accesskey=\"l\">"
2333: + Web.escapeHtml(rb.getString("sit_jumptools"))
2334: + "</a>");
2335: out.println("<a href=\"#sitetabs\" class=\"skip\" title=\""
2336: + Web.escapeHtml(rb.getString("sit_jumpworksite"))
2337: + "\" accesskey=\"w\">"
2338: + Web.escapeHtml(rb.getString("sit_jumpworksite"))
2339: + "</a>");
2340: out.println("</div>");
2341: if (loggedIn) {
2342: out.println("<div id=\"headerMax\">");
2343: } else {
2344: out.println("<div id=\"headerMin\">");
2345: }
2346:
2347: try {
2348: if (loggedIn) {
2349: includeLogo(out, req, session, siteId);
2350: includeTabs(out, req, session, siteId, "site", false);
2351: } else {
2352: includeLogo(out, req, session, siteId);
2353: out
2354: .println("<div class=\"divColor\" id=\"tabBottom\"><br /></div></div>");
2355: }
2356: } catch (Exception any) {
2357: }
2358:
2359: out.println("</div>");
2360: }
2361:
2362: protected void includeTabs(PrintWriter out, HttpServletRequest req,
2363: Session session, String siteId, String prefix,
2364: boolean addLogout) throws IOException {
2365: // for skinning
2366: String siteType = calcSiteType(siteId);
2367:
2368: // If we have turned on auto-state reset on navigation, we generate the
2369: // "site-reset" "worksite-reset" and "gallery-reset" urls
2370: if ("true".equals(ServerConfigurationService
2371: .getString(CONFIG_AUTO_RESET))) {
2372: prefix = prefix + "-reset";
2373: }
2374:
2375: // is the current site the end user's My Workspace?
2376: // Note: the site id can match the user's id or eid
2377: String curUserId = session.getUserId();
2378: String curUserEid = curUserId;
2379: if (siteId != null) {
2380: try {
2381: curUserEid = UserDirectoryService.getUserEid(curUserId);
2382: } catch (UserNotDefinedException e) {
2383: }
2384: }
2385: boolean curMyWorkspace = ((siteId == null) || (SiteService
2386: .isUserSite(siteId) && ((SiteService.getSiteUserId(
2387: siteId).equals(curUserId) || SiteService.getSiteUserId(
2388: siteId).equals(curUserEid)))));
2389:
2390: // if this is a My Workspace, it gets its own tab and should not be
2391: // considered in the other tab logic
2392: if (curMyWorkspace)
2393: siteId = null;
2394:
2395: // collect the user's sites
2396: List mySites = SiteService
2397: .getSites(
2398: org.sakaiproject.site.api.SiteService.SelectionType.ACCESS,
2399: null,
2400: null,
2401: null,
2402: org.sakaiproject.site.api.SiteService.SortType.TITLE_ASC,
2403: null);
2404:
2405: // collect the user's preferences
2406: int prefTabs = 4;
2407: List prefExclude = new Vector();
2408: List prefOrder = new Vector();
2409: if (session.getUserId() != null) {
2410: Preferences prefs = PreferencesService
2411: .getPreferences(session.getUserId());
2412: ResourceProperties props = prefs
2413: .getProperties("sakai:portal:sitenav");
2414: try {
2415: prefTabs = (int) props.getLongProperty("tabs");
2416: } catch (Exception any) {
2417: }
2418:
2419: List l = props.getPropertyList("exclude");
2420: if (l != null) {
2421: prefExclude = l;
2422: }
2423:
2424: l = props.getPropertyList("order");
2425: if (l != null) {
2426: prefOrder = l;
2427: }
2428: }
2429:
2430: // the number of tabs to display
2431: int tabsToDisplay = prefTabs;
2432:
2433: // remove all in exclude from mySites
2434: mySites.removeAll(prefExclude);
2435:
2436: // re-order mySites to have order first, the rest later
2437: List ordered = new Vector();
2438: for (Iterator i = prefOrder.iterator(); i.hasNext();) {
2439: String id = (String) i.next();
2440:
2441: // find this site in the mySites list
2442: int pos = indexOf(id, mySites);
2443: if (pos != -1) {
2444: // move it from mySites to order
2445: Site s = (Site) mySites.get(pos);
2446: ordered.add(s);
2447: mySites.remove(pos);
2448: }
2449: }
2450:
2451: // pick up the rest of the sites
2452: ordered.addAll(mySites);
2453: mySites = ordered;
2454:
2455: // split into 2 lists - the first n, and the rest
2456: List moreSites = new Vector();
2457: if (mySites.size() > tabsToDisplay) {
2458: int remove = mySites.size() - tabsToDisplay;
2459: for (int i = 0; i < remove; i++) {
2460: Site site = (Site) mySites.get(tabsToDisplay);
2461:
2462: // add to more unless it's the current site (it will get an
2463: // extra tag)
2464: if (!site.getId().equals(siteId)) {
2465: moreSites.add(site);
2466: }
2467:
2468: // remove from the display list
2469: mySites.remove(tabsToDisplay);
2470: }
2471: }
2472:
2473: // if more has just one, put it back on the main list
2474: if (moreSites.size() == 1) {
2475: mySites.add(moreSites.get(0));
2476: moreSites.clear();
2477: }
2478:
2479: // check if the current site is missing from the main list
2480: String extraTitle = null;
2481: if (siteId != null) {
2482: boolean extra = true;
2483: for (Iterator i = mySites.iterator(); i.hasNext();) {
2484: Site site = (Site) i.next();
2485: if (site.getId().equals(siteId)) {
2486: extra = false;
2487: break;
2488: }
2489: }
2490: if (extra) {
2491: try {
2492: Site site = SiteService.getSite(siteId);
2493: extraTitle = site.getTitle();
2494: } catch (IdUnusedException e) {
2495: // check for another user's myWorkspace by eid
2496: if (SiteService.isUserSite(siteId)) {
2497: String userEid = SiteService
2498: .getSiteUserId(siteId);
2499: try {
2500: String userId = UserDirectoryService
2501: .getUserId(userEid);
2502: Site site = SiteService.getSite(SiteService
2503: .getUserSiteId(userId));
2504: extraTitle = site.getTitle();
2505: } catch (UserNotDefinedException ee) {
2506: M_log
2507: .warn("includeTabs: cur site not found (not ~eid): "
2508: + siteId);
2509: } catch (IdUnusedException ee) {
2510: M_log
2511: .warn("includeTabs: cur site not found (assumed ~eid, didn't find site): "
2512: + siteId);
2513: }
2514: } else {
2515: M_log.warn("includeTabs: cur site not found: "
2516: + siteId);
2517: }
2518: }
2519: }
2520: }
2521:
2522: String cssClass = (siteType != null) ? "siteNavWrap "
2523: + siteType : "siteNavWrap";
2524: out.println("<div class=\"" + cssClass + "\">");
2525: out.println(" <div id=\"siteNav\">");
2526: // out.println(" <tr>");
2527: out.println(" <div id=\"linkNav\">");
2528:
2529: // target for "jump to tabs" link and header
2530:
2531: out
2532: .println(" <a id=\"sitetabs\" class=\"skip\" name=\"sitetabs\"></a>");
2533: out.println(" <h1 class=\"skip\">"
2534: + Web.escapeHtml(rb.getString("sit_worksiteshead"))
2535: + "</h1>");
2536:
2537: out.println(" <ul id=\"siteLinkList\">");
2538:
2539: // myWorkspace
2540: if (curMyWorkspace) {
2541: out
2542: .println(" <li class=\"selectedTab\"><a href=\"#\"><span>"
2543: + rb.getString("sit_mywor")
2544: + "</span></a></li>");
2545: } else {
2546: String siteUrl = Web.serverUrl(req)
2547: + ServerConfigurationService
2548: .getString("portalPath")
2549: + "/"
2550: + prefix
2551: + "/"
2552: + Web.escapeUrl(getUserEidBasedSiteId(session
2553: .getUserId()));
2554: out.println(" <li><a href=\"" + siteUrl
2555: + "\" target=\"_parent\" title=\""
2556: + Web.escapeHtml(rb.getString("sit_mywor"))
2557: + "\"><span>"
2558: + Web.escapeHtml(rb.getString("sit_mywor"))
2559: + "</span></a></li>");
2560: }
2561:
2562: // first n tabs
2563: for (Iterator i = mySites.iterator(); i.hasNext();) {
2564: Site s = (Site) i.next();
2565: if (s.getId().equals(siteId)) {
2566: out
2567: .println(" <li class=\"selectedTab\"><a href=\"#\"><span>"
2568: + Web.escapeHtml(s.getTitle())
2569: + "</span></a></li>");
2570: } else {
2571: String siteUrl = Web.serverUrl(req)
2572: + ServerConfigurationService
2573: .getString("portalPath") + "/" + prefix
2574: + "/" + Web.escapeUrl(getSiteEffectiveId(s));
2575: out.println(" <li><a href=\"" + siteUrl
2576: + "\" target=\"_parent\" title=\""
2577: + Web.escapeHtml(s.getTitle()) + " "
2578: + Web.escapeHtml(rb.getString("sit_worksite"))
2579: + "\"><span>" + Web.escapeHtml(s.getTitle())
2580: + "</span></a></li>");
2581: }
2582: }
2583:
2584: // current site, if not in the list of first n tabs
2585: if (extraTitle != null) {
2586: out.println(" <li class=\"selectedTab\"><a><span>"
2587: + Web.escapeHtml(extraTitle) + "</span></a></li>");
2588: }
2589:
2590: out
2591: .println(" <li style=\"display:none;border-width:0\" class=\"fixTabsIE\">"
2592: + "<a href=\"javascript:void(0);\">#x20;</a></li>");
2593: out.println(" </ul>");
2594: out.println(" </div>");
2595:
2596: // more dropdown
2597: if (moreSites.size() > 0) {
2598: out
2599: .println(" <div id=\"selectNav\"><span class=\"skip\">"
2600: + Web.escapeHtml(rb
2601: .getString("sit_selectmessage"))
2602: + "</span>");
2603: out.println(" <select ");
2604: out
2605: .println(" onchange=\"if (this.options[this.selectedIndex].value != '')"
2606: + " { parent.location = this.options[this.selectedIndex].value; } else { this.selectedIndex = 0; }\">");
2607: out
2608: .println(" <option value=\"\" selected=\"selected\">"
2609: + Web.escapeHtml(rb.getString("sit_more"))
2610: + "</option>");
2611:
2612: for (Iterator i = moreSites.iterator(); i.hasNext();) {
2613: Site s = (Site) i.next();
2614: String siteUrl = Web.serverUrl(req)
2615: + ServerConfigurationService
2616: .getString("portalPath") + "/" + prefix
2617: + "/" + getSiteEffectiveId(s);
2618: out.println(" <option title=\""
2619: + Web.escapeHtml(s.getTitle()) + " "
2620: + Web.escapeHtml(rb.getString("sit_worksite"))
2621: + "\" value=\"" + siteUrl + "\">"
2622: + Web.escapeHtml(s.getTitle()) + "</option> ");
2623: }
2624:
2625: out.println(" </select>");
2626: out.println(" </div>");
2627: }
2628:
2629: if (addLogout) {
2630: String logoutUrl = Web.serverUrl(req)
2631: + ServerConfigurationService
2632: .getString("portalPath")
2633: + "/logout_gallery";
2634: out.println("<div class=\"galleryLogin\">");
2635: out.println(" <a href=\"" + logoutUrl
2636: + "\" target=\"_parent\">"
2637: + Web.escapeHtml(rb.getString("sit_log")) + "</a>");
2638: out.println("</div>");
2639: }
2640: // out.println(" </tr>");
2641: out.println(" </div>");
2642: out
2643: .println("<div class=\"divColor\" id=\"tabBottom\"></div></div>");
2644: if (addLogout) {
2645: } else {
2646: out.println(" </div>");
2647: }
2648: }
2649:
2650: protected void includeTool(HttpServletRequest req,
2651: HttpServletResponse res, ToolConfiguration placement)
2652: throws IOException {
2653: PrintWriter out = res.getWriter();
2654:
2655: // find the tool registered for this
2656: ActiveTool tool = ActiveToolManager.getActiveTool(placement
2657: .getToolId());
2658: if (tool == null) {
2659: // doError(req, res, session);
2660: return;
2661: }
2662:
2663: // let the tool do some the work (include) (see note above)
2664: String toolUrl = ServerConfigurationService.getToolUrl() + "/"
2665: + Web.escapeUrl(placement.getId());
2666:
2667: // Reset the tool state if requested
2668: if (portalService.isResetRequested(req)) {
2669: Session s = SessionManager.getCurrentSession();
2670: ToolSession ts = s.getToolSession(placement.getId());
2671: ts.clearAttributes();
2672: }
2673:
2674: // this is based on what varuna is currently putting out
2675: out.println("<div class=\"portlet\">");
2676: out.println("<div class=\"portletTitleWrap\">");
2677:
2678: // emit title information
2679:
2680: // for the reset button
2681: boolean showResetButton = !"false".equals(placement.getConfig()
2682: .getProperty(TOOLCONFIG_SHOW_RESET_BUTTON));
2683:
2684: // for the help button
2685: // get the help document ID from the tool config (tool registration
2686: // usually).
2687: // The help document ID defaults to the tool ID
2688: boolean helpEnabledGlobally = ServerConfigurationService
2689: .getBoolean("display.help.icon", true);
2690: boolean helpEnabledInTool = !"false".equals(placement
2691: .getConfig().getProperty(TOOLCONFIG_SHOW_HELP_BUTTON));
2692: boolean showHelpButton = helpEnabledGlobally
2693: && helpEnabledInTool;
2694:
2695: String helpActionUrl = "";
2696: if (showHelpButton) {
2697: String helpDocId = placement.getConfig().getProperty(
2698: TOOLCONFIG_HELP_DOCUMENT_ID);
2699: String helpDocUrl = placement.getConfig().getProperty(
2700: TOOLCONFIG_HELP_DOCUMENT_URL);
2701: if (helpDocUrl != null && helpDocUrl.length() > 0) {
2702: helpActionUrl = helpDocUrl;
2703: } else {
2704: if (helpDocId == null || helpDocId.length() == 0) {
2705: helpDocId = tool.getId();
2706: }
2707: helpActionUrl = ServerConfigurationService
2708: .getHelpUrl(helpDocId);
2709: }
2710: }
2711:
2712: out.write("<div class=\"portletTitle\">\n");
2713: out.write("\t<div class=\"title\">\n");
2714:
2715: RenderResult result = ToolRenderService.render(placement, req,
2716: res, getServletContext());
2717:
2718: // This is a new-style reset where the button is in the background
2719: // document
2720: if (showResetButton) {
2721: // Note: This is somewhat brittle code as it assumes that the url
2722: // will
2723: // always be /tool/ - as an example - one thing that might fail
2724: // would
2725: // be if the /portal/ string were /tool/ so the right tool url would
2726: // be
2727: // http://localhost:8080/tool/tool/ - then this code would break
2728:
2729: // Send the reset url through a redirect step so that any future
2730: // refresh of the tool's iframe do not cause a reset
2731: String resetUrl = PortalStringUtil.replaceFirst(toolUrl,
2732: "/tool/", "/tool-reset/");
2733: out
2734: .write("\t\t<a href=\""
2735: + resetUrl
2736: + "?panel=Main\" "
2737: + " target=\""
2738: + Web.escapeJavascript("Main"
2739: + placement.getId())
2740: + "\""
2741: + " title=\""
2742: + Web.escapeHtml(rb.getString("sit_reset"))
2743: + "\"><img src=\"/library/image/transparent.gif\" alt=\""
2744: + Web.escapeHtml(rb.getString("sit_reset"))
2745: + "\" border=\"1\" /></a>");
2746: }
2747: out
2748: .write("<h2>" + result.getTitle() + "\n"
2749: + "\t</h2></div>\n");
2750: out.write("\t<div class=\"action\">\n");
2751: if (showHelpButton) {
2752: out.write(makeHelpButton(helpActionUrl));
2753: }
2754: out.write("\t</div><!--gsilver end of the action-->\n");
2755: out.write("</div><!--gsilver end of the portletTitle-->\n");
2756: out.write("</div><!--gsilver end of the portletTitleWrap-->\n");
2757:
2758: // Output the iframe for the tool content
2759: out.println("<div class=\"portletMainWrap\">");
2760:
2761: out.println(result.getContent());
2762:
2763: out
2764: .println("</div><!--gsilver end of the portletMainWrap--></div><!--gsilver end of the portlet-->");
2765: }
2766:
2767: protected void includeWorksite(HttpServletRequest req,
2768: HttpServletResponse res, Session session, Site site,
2769: SitePage page, String toolContextPath, String portalPrefix)
2770: throws IOException {
2771: // add the page navigation with presence
2772: includePageNav(req, res, session, site, page, toolContextPath,
2773: portalPrefix);
2774:
2775: // add the page
2776: includePage(req, res, page, toolContextPath, "content");
2777: }
2778:
2779: /**
2780: * Initialize the servlet.
2781: *
2782: * @param config
2783: * The servlet config.
2784: * @throws ServletException
2785: */
2786: public void init(ServletConfig config) throws ServletException {
2787: super .init(config);
2788: portalService = org.sakaiproject.portal.api.cover.PortalService
2789: .getInstance();
2790:
2791: M_log.info("init()");
2792:
2793: basicAuth = new BasicAuth();
2794: basicAuth.init();
2795:
2796: enableDirect = "true".equals(ServerConfigurationService
2797: .getString("charon.directurl", "true"));
2798: }
2799:
2800: /**
2801: * Send the POST request to login
2802: *
2803: * @param req
2804: * @param res
2805: * @param session
2806: * @throws IOException
2807: */
2808: protected void postLogin(HttpServletRequest req,
2809: HttpServletResponse res, Session session, String loginPath)
2810: throws ToolException {
2811: ActiveTool tool = ActiveToolManager
2812: .getActiveTool("sakai.login");
2813: String context = req.getContextPath() + req.getServletPath()
2814: + "/" + loginPath;
2815: tool.help(req, res, context, "/" + loginPath);
2816: }
2817:
2818: /**
2819: * Output some session information
2820: *
2821: * @param out
2822: * The print writer
2823: * @param html
2824: * If true, output in HTML, else in text.
2825: */
2826: protected void showSession(PrintWriter out, boolean html) {
2827: // get the current user session information
2828: Session s = SessionManager.getCurrentSession();
2829: if (s == null) {
2830: out.println("no session established");
2831: if (html)
2832: out.println("<br />");
2833: } else {
2834: out.println("session: "
2835: + s.getId()
2836: + " user id: "
2837: + s.getUserId()
2838: + " enterprise id: "
2839: + s.getUserEid()
2840: + " started: "
2841: + DateFormat.getDateInstance().format(
2842: new Date(s.getCreationTime()))
2843: + " accessed: "
2844: + DateFormat.getDateInstance().format(
2845: new Date(s.getLastAccessedTime()))
2846: + " inactive after: " + s.getMaxInactiveInterval());
2847: if (html)
2848: out.println("<br />");
2849: }
2850:
2851: ToolSession ts = SessionManager.getCurrentToolSession();
2852: if (ts == null) {
2853: out.println("no tool session established");
2854: if (html)
2855: out.println("<br />");
2856: } else {
2857: out.println("tool session: "
2858: + ts.getId()
2859: + " started: "
2860: + DateFormat.getDateInstance().format(
2861: new Date(ts.getCreationTime()))
2862: + " accessed: "
2863: + DateFormat.getDateInstance().format(
2864: new Date(ts.getLastAccessedTime())));
2865: if (html)
2866: out.println("<br />");
2867: }
2868: }
2869:
2870: protected PrintWriter startResponse(HttpServletResponse res,
2871: String title, String skin, boolean top) throws IOException {
2872: // headers
2873: res.setContentType("text/html; charset=UTF-8");
2874: res.addDateHeader("Expires", System.currentTimeMillis()
2875: - (1000L * 60L * 60L * 24L * 365L));
2876: res.addDateHeader("Last-Modified", System.currentTimeMillis());
2877: res
2878: .addHeader("Cache-Control",
2879: "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0");
2880: res.addHeader("Pragma", "no-cache");
2881:
2882: // get the writer
2883: PrintWriter out = res.getWriter();
2884:
2885: // form the head
2886: out
2887: .println("<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" "
2888: + "\"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">"
2889: + "<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"en\" xml:lang=\"en\">"
2890: + " <head>"
2891: + " <meta http-equiv=\"Content-Type\" content=\"text/html; charset=UTF-8\" />");
2892:
2893: // pick the one full portal skin
2894: if (skin == null) {
2895: skin = ServerConfigurationService.getString("skin.default");
2896: }
2897: String skinRepo = ServerConfigurationService
2898: .getString("skin.repo");
2899:
2900: out
2901: .println(" <link href=\""
2902: + skinRepo
2903: + "/"
2904: + skin
2905: + "/portal.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />");
2906: out
2907: .println(" <meta http-equiv=\"Content-Style-Type\" content=\"text/css\" />"
2908: + " <title>"
2909: + Web.escapeHtml(title)
2910: + "</title>"
2911: + " <script type=\"text/javascript\" language=\"JavaScript\" src=\""
2912: + getScriptPath()
2913: + "headscripts.js\"></script>" + " </head>");
2914:
2915: // start the body
2916: out.println("<body class=\"portalBody\">");
2917:
2918: // if top, mark this as the portal window
2919: if (top) {
2920: out
2921: .println("<script type=\"text/javascript\" language=\"JavaScript\">");
2922: out.println("var sakaiPortalWindow = \"\";");
2923: out.println("</script>");
2924: }
2925:
2926: return out;
2927: }
2928:
2929: /**
2930: * Returns the type ("course", "project", "workspace", "mySpecialSiteType",
2931: * etc) of the given site; special handling of returning "workspace" for
2932: * user workspace sites. This method is tightly coupled to site skinning.
2933: */
2934: protected String calcSiteType(String siteId) {
2935: String siteType = null;
2936: if (siteId != null && siteId.length() != 0) {
2937: if (SiteService.isUserSite(siteId)) {
2938: siteType = "workspace";
2939: } else {
2940: try {
2941: siteType = SiteService.getSite(siteId).getType();
2942: } catch (IdUnusedException ex) {
2943: // ignore, the site wasn't found
2944: }
2945: }
2946: }
2947:
2948: if (siteType != null && siteType.trim().length() == 0)
2949: siteType = null;
2950: return siteType;
2951: }
2952:
2953: /**
2954: * Find the site in the list that has this id - return the position.
2955: *
2956: * @param value
2957: * The site id to find.
2958: * @param siteList
2959: * The list of Site objects.
2960: * @return The index position in siteList of the site with site id = value,
2961: * or -1 if not found.
2962: */
2963: protected int indexOf(String value, List siteList) {
2964: for (int i = 0; i < siteList.size(); i++) {
2965: Site site = (Site) siteList.get(i);
2966: if (site.equals(value)) {
2967: return i;
2968: }
2969: }
2970:
2971: return -1;
2972: }
2973:
2974: /**
2975: * Check for any just expired sessions and redirect
2976: *
2977: * @return true if we redirected, false if not
2978: */
2979: protected boolean redirectIfLoggedOut(HttpServletResponse res)
2980: throws IOException {
2981: // if we are in a newly created session where we had an invalid
2982: // (presumed timed out) session in the request,
2983: // send script to cause a sakai top level redirect
2984: if (ThreadLocalManager
2985: .get(SessionManager.CURRENT_INVALID_SESSION) != null) {
2986: String loggedOutUrl = ServerConfigurationService
2987: .getLoggedOutUrl();
2988: sendPortalRedirect(res, loggedOutUrl);
2989: return true;
2990: }
2991:
2992: return false;
2993: }
2994:
2995: /**
2996: * Send a redirect so our Portal window ends up at the url, via javascript.
2997: *
2998: * @param url
2999: * The redirect url
3000: */
3001: protected void sendPortalRedirect(HttpServletResponse res,
3002: String url) throws IOException {
3003: PrintWriter out = startResponse(res, null, null, false);
3004: out
3005: .println("<script type=\"text/javascript\" language=\"JavaScript\">");
3006: out.println("portalWindowRefresh('" + url + "');");
3007: out.println("</script>");
3008: endResponse(out);
3009: }
3010:
3011: /**
3012: * Compute the string that will identify the user site for this user - use
3013: * the EID if possible
3014: *
3015: * @param userId
3016: * The user id
3017: * @return The site "ID" but based on the user EID
3018: */
3019: protected String getUserEidBasedSiteId(String userId) {
3020: try {
3021: // use the user EID
3022: String eid = UserDirectoryService.getUserEid(userId);
3023: return SiteService.getUserSiteId(eid);
3024: } catch (UserNotDefinedException e) {
3025: M_log
3026: .warn("getUserEidBasedSiteId: user id not found for eid: "
3027: + userId);
3028: return SiteService.getUserSiteId(userId);
3029: }
3030: }
3031:
3032: /**
3033: * If this is a user site, return an id based on the user EID, otherwise
3034: * just return the site id.
3035: *
3036: * @param site
3037: * The site.
3038: * @return The effective site id.
3039: */
3040: protected String getSiteEffectiveId(Site site) {
3041: if (SiteService.isUserSite(site.getId())) {
3042: try {
3043: String userId = SiteService.getSiteUserId(site.getId());
3044: String eid = UserDirectoryService.getUserEid(userId);
3045: return SiteService.getUserSiteId(eid);
3046: } catch (UserNotDefinedException e) {
3047: M_log
3048: .warn("getSiteEffectiveId: user eid not found for user site: "
3049: + site.getId());
3050: }
3051: }
3052:
3053: return site.getId();
3054: }
3055:
3056: /**
3057: * Do the getSiteVisit, but if not found and the id is a user site, try
3058: * translating from user EID to ID.
3059: *
3060: * @param siteId
3061: * The Site Id.
3062: * @return The Site.
3063: * @throws PermissionException
3064: * If not allowed.
3065: * @throws IdUnusedException
3066: * If not found.
3067: */
3068: protected Site getSiteVisit(String siteId)
3069: throws PermissionException, IdUnusedException {
3070: try {
3071: return SiteService.getSiteVisit(siteId);
3072: } catch (IdUnusedException e) {
3073: if (SiteService.isUserSite(siteId)) {
3074: try {
3075: String userEid = SiteService.getSiteUserId(siteId);
3076: String userId = UserDirectoryService
3077: .getUserId(userEid);
3078: String alternateSiteId = SiteService
3079: .getUserSiteId(userId);
3080: return SiteService.getSiteVisit(alternateSiteId);
3081: } catch (UserNotDefinedException ee) {
3082: }
3083: }
3084:
3085: // re-throw if that didn't work
3086: throw e;
3087: }
3088: }
3089: }
|