/********************************************************************************** * $URL:https://source.sakaiproject.org/svn/osp/trunk/portal/webapp/src/java/org/theospi/portfolio/portal/web/XsltPortal.java $ * $Id:XsltPortal.java 9134 2006-05-08 20:28:42Z chmaurer@iupui.edu $ *********************************************************************************** * * Copyright (c) 2006, 2007, 2008 The Sakai Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.opensource.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * **********************************************************************************/ package org.theospi.portfolio.portal.web; import javax.xml.transform.TransformerFactory; import javax.xml.transform.OutputKeys; import org.sakaiproject.authz.api.Role; import org.sakaiproject.component.cover.ComponentManager; import org.sakaiproject.component.cover.ServerConfigurationService; import org.sakaiproject.entity.api.ResourceProperties; import org.sakaiproject.exception.IdUnusedException; import org.sakaiproject.exception.PermissionException; import org.sakaiproject.portal.charon.CharonPortal; import org.sakaiproject.site.api.Site; import org.sakaiproject.site.api.SitePage; import org.sakaiproject.site.api.ToolConfiguration; import org.sakaiproject.site.cover.SiteService; import org.sakaiproject.tool.api.*; import org.sakaiproject.tool.cover.ActiveToolManager; import org.sakaiproject.tool.cover.SessionManager; import org.sakaiproject.user.api.Preferences; import org.sakaiproject.user.api.User; import org.sakaiproject.user.cover.PreferencesService; import org.sakaiproject.util.ResourceLoader; import org.apache.commons.lang.StringUtils; import org.sakaiproject.util.Web; import org.theospi.portfolio.portal.intf.PortalManager; import org.theospi.portfolio.portal.model.SitePageWrapper; import org.theospi.portfolio.portal.model.SiteType; import org.theospi.portfolio.portal.model.ToolCategory; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.xml.sax.InputSource; import org.xml.sax.SAXException; import javax.servlet.ServletConfig; import javax.servlet.ServletException; import javax.servlet.ServletContext; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.transform.*; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamResult; import javax.xml.transform.stream.StreamSource; import java.io.*; import java.net.MalformedURLException; import java.net.URL; import java.util.*; import java.util.Map.Entry; /** * Created by IntelliJ IDEA. * User: John Ellis * Date: Feb 9, 2006 * Time: 2:21:33 PM * To change this template use File | Settings | File Templates. */ public class XsltPortal extends CharonPortal { private PortalManager portalManager; private DocumentBuilder documentBuilder; private Templates templates; private Templates toolCategoryTemplates; private URIResolver servletResolver; private String categoryBasePath; /** messages. */ private static ResourceLoader rb = new ResourceLoader("org/theospi/portfolio/portal/messages"); /** base messages. */ private static ResourceLoader rbsitenav = new ResourceLoader("sitenav"); private static final String TOOL_CATEGORY = "category"; private static final String TOOL_CATEGORY_HELPER = "category_helper"; private static final String SITE_TYPE = "site_type"; private static final String SITE_TYPE_HELPER = "site_type_helper"; protected void doPost(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // get the Sakai session Session session = SessionManager.getCurrentSession(); // recognize what to do from the path String option = req.getPathInfo(); // get the parts (the first will be "") String[] parts = option.split("/"); if (parts.length < 2) { super.doPost(req, res); return; } if (parts[1].equals(SITE_TYPE_HELPER)) { // Resolve the site_type of the form /portal/site_type_helper/project String siteTypeKey = parts[2]; doSiteTypeHelper(req, res, session, siteTypeKey, parts.length == 4); } else { super.doPost(req, res); } } protected void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException { // get the Sakai session Session session = SessionManager.getCurrentSession(); // recognize what to do from the path String option = req.getPathInfo(); // get the parts (the first will be "") String[] parts = option.split("/"); if (parts.length < 2) { super.doGet(req, res); return; } if (parts[1].equals(SITE_TYPE)) { // Resolve the site_type of the form /portal/site_type/project String siteTypeKey = parts[2]; doSiteType(req, res, session, siteTypeKey); } else if (parts[1].equals(SITE_TYPE_HELPER)) { // Resolve the site_type of the form /portal/site_type_helper/project String siteTypeKey = parts[2]; doSiteTypeHelper(req, res, session, siteTypeKey, parts.length == 4); } else if (parts[1].equals(TOOL_CATEGORY)) { // Resolve the site_type of the form /portal/category/<siteId>/<categoryKey>/<optionalToolId> String siteId = parts[2]; String categoryKey = parts[3]; String pageId = null; if (parts.length > 4) { pageId = parts[4]; } doCategory(req, res, session, siteId, categoryKey, pageId); } else if (parts[1].equals(TOOL_CATEGORY_HELPER)) { // Resolve the site_type of the form /portal/category_helper/<siteId>/<categoryKey> String siteId = parts[2]; String categoryKey = parts[3]; doCategoryHelper(req, res, session, siteId, categoryKey, parts.length > 4); } else { super.doGet(req, res); } } protected void forwardPortal(ActiveTool tool, HttpServletRequest req, HttpServletResponse res, ToolConfiguration p, String skin, String toolContextPath, String toolPathInfo) throws ToolException, IOException { // if there is a stored request state, and path, extract that from the // session and // reinstance it // generate the forward to the tool page placement String portalPlacementUrl = getPortalString() + super.getPortalPageUrl(p); res.sendRedirect(portalPlacementUrl); return; } protected String getPortalString() { return "/osp-portal"; } protected void doCategoryHelper(HttpServletRequest req, HttpServletResponse res, Session session, String siteId, String categoryKey, boolean returning) throws ToolException, IOException { if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); return; } Site site = getPortalManager().getSite(siteId); String siteTypeKey = getPortalManager().decorateSiteType(site); SiteType siteType = getPortalManager().getSiteType(siteTypeKey); Document doc = getDocumentBuilder().newDocument(); Element root = doc.createElement("toolCategory"); ToolCategory category = getPortalManager().getToolCategory(siteType.getKey(), categoryKey); Map categoryPageMap = getPortalManager().getPagesByCategory(siteId); List categoryPages = (List) categoryPageMap.get(category); root.appendChild(createCategoryXml(doc, category, categoryPages, siteId, categoryKey, null)); Element rolesElement = createRolesXml(doc, siteId); root.appendChild(rolesElement); doc.appendChild(root); outputDocument(req, res, session, doc, getToolCategoryTransformer()); /* ToolSession toolSession = session.getToolSession(Web.escapeJavascript(categoryKey)); if (!returning) { toolSession.setAttribute(PortalManager.SITE_TYPE, siteTypeKey); toolSession.setAttribute(PortalManager.SITE_ID, siteId); toolSession.setAttribute(PortalManager.TOOL_CATEGORY, categoryKey); toolSession.setAttribute(PortalManager.CONTEXT, getContext()); } // put the session in the request attribute req.setAttribute(Tool.TOOL_SESSION, toolSession); // set as the current tool session SessionManager.setCurrentToolSession(toolSession); // put the placement id in the request attribute String placementId = Web.escapeJavascript(categoryKey); req.setAttribute(Tool.PLACEMENT_ID, placementId); ActiveTool helperTool = ActiveToolManager.getActiveTool("osp.tool.category"); Placement placement = new org.sakaiproject.util.Placement(placementId, helperTool, null, null, null); String context = req.getPathInfo(); forwardTool(helperTool, req, res, placement, siteType.getSkin(), getContext() + "/" + context, "/toolCategory"); */ } protected Element createRolesXml(Document doc, String siteId) { Element rolesElement = doc.createElement("roles"); List roles = getPortalManager().getRoles(siteId); for (Iterator i=roles.iterator();i.hasNext();) { Role role = (Role) i.next(); if (role != null) { Element roleElement = doc.createElement("role"); roleElement.setAttribute("id", role.getId()); rolesElement.appendChild(roleElement); } } return rolesElement; } protected void doSiteTypeHelper(HttpServletRequest req, HttpServletResponse res, Session session, String siteTypeKey, boolean returning) throws ToolException { if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); return; } SiteType siteType = getPortalManager().getSiteType(siteTypeKey); ToolSession toolSession = session.getToolSession(Web.escapeJavascript(siteTypeKey)); toolSession.setAttribute(PortalManager.RELOAD_SITES, "true"); if (!returning) { toolSession.setAttribute(PortalManager.SITE_TYPE, siteTypeKey); } // put the session in the request attribute req.setAttribute(Tool.TOOL_SESSION, toolSession); // set as the current tool session SessionManager.setCurrentToolSession(toolSession); // put the placement id in the request attribute String placementId = Web.escapeJavascript(siteTypeKey); req.setAttribute(Tool.PLACEMENT_ID, placementId); ActiveTool helperTool = ActiveToolManager.getActiveTool("osp.site.type"); Placement placement = new org.sakaiproject.util.Placement( placementId, "osp.site.type", helperTool, null, null, null); String context = req.getPathInfo(); forwardTool(helperTool, req, res, placement, siteType.getSkin(), getContext() + "/" + context, "/siteType"); } protected void doCategory(HttpServletRequest req, HttpServletResponse res, Session session, String siteId, String categoryKey, String pageId) throws IOException, ToolException { siteId = checkVisitSite(siteId, session, req, res); if (siteId == null) { return; } Document doc = createPortalDocument(session, null, siteId, categoryKey, pageId, req); outputDocument(req, res, session, doc); } protected void doSiteType(HttpServletRequest req, HttpServletResponse res, Session session, String siteTypeKey) throws IOException, ToolException { if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); return; } Document doc = createPortalDocument(session, siteTypeKey, null, null, null, req); outputDocument(req, res, session, doc); } protected void outputDocument(HttpServletRequest req, HttpServletResponse res, Session session, Document doc) throws IOException { outputDocument(req, res, session, doc, getTransformer()); } protected void outputDocument(HttpServletRequest req, HttpServletResponse res, Session session, Document doc, Transformer transformer) throws IOException { res.setContentType("text/html; charset=UTF-8"); res.addDateHeader("Expires", System.currentTimeMillis() - (1000L * 60L * 60L * 24L * 365L)); res.addDateHeader("Last-Modified", System.currentTimeMillis()); res.addHeader("Cache-Control", "no-store, no-cache, must-revalidate, max-age=0, post-check=0, pre-check=0"); res.addHeader("Pragma", "no-cache"); PrintWriter out = res.getWriter(); try { StreamResult outputTarget = new StreamResult(out); transformer.transform(new DOMSource(doc), outputTarget); } catch (TransformerException e) { throw new RuntimeException(e); } } protected void doSite(HttpServletRequest req, HttpServletResponse res, Session session, String siteId, String pageId, String toolContextPath) throws IOException, ToolException { siteId = checkVisitSite(siteId, session, req, res); if (siteId == null) { return; } Document doc = createPortalDocument(session, null, siteId, null, pageId, req); outputDocument(req, res, session, doc); } protected void doWorksite(HttpServletRequest req, HttpServletResponse res, Session session, String siteId, String pageId, String toolContextPath) throws IOException, ToolException { siteId = checkVisitSite(siteId, session, req, res); if (siteId == null) { return; } Document doc = createPortalDocument(session, null, siteId, null, pageId, req); outputDocument(req, res, session, doc); } protected void doPage(HttpServletRequest req, HttpServletResponse res, Session session, String pageId, String toolContextPath) throws IOException, ToolException { SitePage page = getPortalManager().getSitePage(pageId); if (page == null) { doError(req, res, session, ERROR_WORKSITE); return; } String siteId = page.getSiteId(); siteId = checkVisitSite(siteId, session, req, res); if (siteId == null) { return; } Document doc = createPortalDocument(session, null, siteId, getPortalManager().getPageCategory(siteId, pageId), pageId, req); outputDocument(req, res, session, doc); } protected void postLogin(HttpServletRequest req, HttpServletResponse res, Session session, String loginPath) throws ToolException { if (session.getAttribute(Tool.HELPER_DONE_URL) == null) { session.setAttribute(Tool.HELPER_DONE_URL, Web.returnUrl(req, null)); } super.postLogin(req, res, session, loginPath); } protected Document createPortalDocument(Session session, String siteTypeKey, String siteId, String toolCategoryKey, String pageId, HttpServletRequest req) throws IOException, ToolException { Document doc = getDocumentBuilder().newDocument(); Element root = doc.createElement("portal"); doc.appendChild(root); User currentUser = getPortalManager().getCurrentUser(); boolean loggedIn = false; if (currentUser != null && currentUser.getId().length() > 0) { root.appendChild(createUserXml(doc, currentUser)); loggedIn = true; } root.appendChild(createLoginXml(doc, req)); Map siteTypesMap = getPortalManager().getSitesByType(siteId); Site site = null; SitePage page = null; if (siteId != null) { site = getPortalManager().getSite(siteId); } if (pageId != null) { page = getPortalManager().getSitePage(pageId); } if (siteTypeKey == null) { siteTypeKey = getPortalManager().decorateSiteType(site); } SiteType siteType = findSiteType(siteTypesMap, siteTypeKey); root.appendChild(createTitleXml(doc, site, page)); List skins = getSkins(siteType, site); root.appendChild(createSkinsXml(doc, skins)); root.appendChild(createConfixXml(doc, skins, site, loggedIn)); root.appendChild(createSiteTypesXml(doc, siteTypesMap, siteTypeKey, siteId)); if (siteId != null) { Map pageCateogries = getPortalManager().getPagesByCategory(siteId); checkToolPermissions(pageCateogries); if (pageId == null && toolCategoryKey == null) { // need to pick first page or category ToolCategory category = findFirstCategory(pageCateogries); if (category.getKey().equals(ToolCategory.UNCATEGORIZED_KEY)) { List pages = (List) pageCateogries.get(category); pageId = findFirstPage(pages); } else { toolCategoryKey = category.getKey(); } } root.appendChild(createPageCategoriesXml(doc, pageCateogries, siteId, toolCategoryKey, pageId)); } if (siteId != null) { Element rolesElement = createRolesXml(doc, siteId); root.appendChild(rolesElement); } if (!getPortalManager().isDisplaySiteTypes()) { try { root.appendChild(createSitesTabArea(session, siteId, doc, req)); } catch (SAXException e) { throw new ToolException(e); } } root.appendChild(createExternalizedXml(doc)); return doc; } protected void checkToolPermissions(Map pages) { List emptyCategories = new ArrayList(); for (Iterator<ToolCategory> i=pages.entrySet().iterator();i.hasNext();) { Entry entry = (Entry) i.next(); ToolCategory category = (ToolCategory) entry.getKey(); List categoryPages = (List) entry.getValue(); checkPagesAccess(categoryPages); if (categoryPages.isEmpty()) { emptyCategories.add(category); } } for (Iterator<ToolCategory> i = emptyCategories.iterator();i.hasNext();) { ToolCategory category = i.next(); pages.remove(category); } } protected void checkPagesAccess(List categoryPages) { for (Iterator<SitePageWrapper> i=categoryPages.iterator();i.hasNext();) { SitePageWrapper page = i.next(); List pageTools = page.getPage().getTools(); if (!checkToolsAccess(page.getPage().getContainingSite(), pageTools)) { i.remove(); } } } protected boolean checkToolsAccess(Site site, List pageTools) { boolean retVal = false; for (Iterator<Placement> i = pageTools.iterator();i.hasNext();) { Placement tool = i.next(); if (allowTool(site, tool)) { retVal = true; } } return retVal; } protected String findFirstPage(List pages) { SitePageWrapper first = null; for (Iterator i=pages.iterator();i.hasNext();) { SitePageWrapper wrapper = (SitePageWrapper) i.next(); if (first == null || first.getOrder() > wrapper.getOrder()) { first = wrapper; } } return first.getPage().getId(); } protected ToolCategory findFirstCategory(Map pageCateogries) { ToolCategory first = null; for (Iterator i=pageCateogries.keySet().iterator();i.hasNext();) { ToolCategory category = (ToolCategory) i.next(); if (first == null || first.getOrder() > category.getOrder()) { first = category; } } return first; } protected SiteType findSiteType(Map siteTypesMap, String siteTypeKey) { for (Iterator i=siteTypesMap.keySet().iterator();i.hasNext();) { SiteType siteType = (SiteType) i.next(); if (siteType.getKey().equals(siteTypeKey)) { return siteType; } } return null; } private Element createSitesTabArea(Session session, String siteId, Document doc, HttpServletRequest req) throws IOException, SAXException { Element siteTabs = doc.createElement("siteTabs"); CharArrayWriter writer = new CharArrayWriter(); PrintWriter printWriter = new PrintWriter(writer); printWriter.write("<div id=\"blank\">"); includeTabs(printWriter, req, session, siteId, "site", false); Document tabs = getDocumentBuilder().parse(new InputSource(new CharArrayReader(writer.toCharArray()))); siteTabs.appendChild(doc.importNode(tabs.getDocumentElement(), true)); return siteTabs; } protected Element createExternalizedXml(Document doc) { Element externalized = doc.createElement("externalized"); for (Iterator i=rb.entrySet().iterator();i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); externalized.appendChild(createExternalizedEntryXml(doc, entry.getKey(), entry.getValue())); } for (Iterator i=rbsitenav.entrySet().iterator();i.hasNext();) { Map.Entry entry = (Map.Entry) i.next(); externalized.appendChild(createExternalizedEntryXml(doc, entry.getKey(), entry.getValue())); } return externalized; } protected Element createExternalizedEntryXml(Document doc, Object key, Object value) { Element entry = doc.createElement("entry"); entry.setAttribute("key", (String) key); appendTextElementNode(doc, "value", (String) value, entry); return entry; } protected Element createTitleXml(Document doc, Site site, SitePage page) { Element titleElement = doc.createElement("pageTitle"); String title = ServerConfigurationService.getString("ui.service"); if (site != null) { title += ":" + site.getTitle(); } if (page != null) { title += ":" + page.getTitle(); } safeAppendTextNode(doc, titleElement, title, true); return titleElement; } protected Element createConfixXml(Document doc, List skins, Site site, boolean loggedIn) { Element config = doc.createElement("config"); String skinRepo = ServerConfigurationService.getString("skin.repo"); if (skins.size() > 0) { skinRepo += "/" + skins.get(skins.size() - 1); } else { skinRepo += "/" + ServerConfigurationService.getString("skin.default"); } if (site != null) { String presenceUrl = getContext() + "/presence/" + site.getId(); boolean showPresence = ServerConfigurationService.getBoolean("display.users.present", true); Element presence = doc.createElement("presence"); safeAppendTextNode(doc, presence, presenceUrl, true); presence.setAttribute("include", Boolean.valueOf(showPresence && loggedIn).toString()); config.appendChild(presence); } Element logo = doc.createElement("logo"); safeAppendTextNode(doc, logo, skinRepo + "/images/logo_inst.gif", true); Element banner = doc.createElement("banner"); safeAppendTextNode(doc, banner, skinRepo + "/images/banner_inst.gif", true); Element logout = doc.createElement("logout"); safeAppendTextNode(doc, logout, getContext() + "/logout", true); String copyright = ServerConfigurationService.getString("bottom.copyrighttext"); String service = ServerConfigurationService.getString("ui.service", "Sakai"); String serviceVersion = ServerConfigurationService.getString("version.service", "?"); String sakaiVersion = ServerConfigurationService.getString("version.sakai", "?"); String server = ServerConfigurationService.getServerId(); String helpUrl = ServerConfigurationService.getHelpUrl(null); String[] bottomNav = ServerConfigurationService.getStrings("bottomnav"); String[] poweredByUrl = ServerConfigurationService.getStrings("powered.url"); String[] poweredByImage = ServerConfigurationService.getStrings("powered.img"); String[] poweredByAltText = ServerConfigurationService.getStrings("powered.alt"); config.appendChild(logo); config.appendChild(banner); config.appendChild(logout); appendTextElementNode(doc, "copyright", copyright, config); appendTextElementNode(doc, "service", service, config); appendTextElementNode(doc, "serviceVersion", serviceVersion, config); appendTextElementNode(doc, "sakaiVersion", sakaiVersion, config); appendTextElementNode(doc, "server", server, config); appendTextElementNode(doc, "helpUrl", helpUrl, config); appendTextElementNodes(doc, bottomNav, config, "bottomNavs", "bottomNav"); if ((poweredByUrl != null) && (poweredByImage != null) && (poweredByAltText != null) && (poweredByUrl.length == poweredByImage.length) && (poweredByUrl.length == poweredByAltText.length)) { for (int i = 0; i < poweredByUrl.length; i++) { config.appendChild(createPoweredByXml(doc, poweredByAltText[i], poweredByImage[i], poweredByUrl[i])); } } else { config.appendChild(createPoweredByXml(doc, "Powered by Sakai", "/library/image/sakai_powered.gif", "http://sakaiproject.org")); } appendTextElementNodes(doc, poweredByUrl, config, "poweredByUrls", "poweredByUrl"); appendTextElementNodes(doc, poweredByImage, config, "poweredByImages", "poweredByImage"); appendTextElementNodes(doc, poweredByAltText, config, "poweredByAltTexts", "poweredByAltText"); return config; } protected Element createPoweredByXml(Document doc, String text, String image, String url) { Element poweredBy = doc.createElement("poweredBy"); appendTextElementNode(doc, "text", text, poweredBy); appendTextElementNode(doc, "image", image, poweredBy); appendTextElementNode(doc, "url", url, poweredBy); return poweredBy; } protected void appendTextElementNodes(Document doc, String[] strings, Element parent, String topNodeName, String nodeName) { Element topNode = doc.createElement(topNodeName); if (strings == null) { return; } for (int i=0;i<strings.length;i++) { appendTextElementNode(doc, nodeName, strings[i], topNode); } parent.appendChild(topNode); } protected void appendTextElementNode(Document doc, String name, String text, Element parent) { Element element = doc.createElement(name); safeAppendTextNode(doc, element, text, true); parent.appendChild(element); } protected Element createPageCategoriesXml(Document doc, Map pages, String siteId, String toolCategoryKey, String pageId) { Element pagesElement = doc.createElement("categories"); for (Iterator i=pages.entrySet().iterator();i.hasNext();) { Entry entry = (Entry) i.next(); ToolCategory category = (ToolCategory) entry.getKey(); List categoryPageList = (List) entry.getValue(); pagesElement.appendChild(createCategoryXml(doc, category, categoryPageList, siteId, toolCategoryKey, pageId)); } return pagesElement; } protected Element createCategoryXml(Document doc, ToolCategory category, List categoryPageList, String siteId, String categoryKey, String pageId) { Element categoryElement = doc.createElement("category"); boolean selected = category.getKey().equals(categoryKey); categoryElement.setAttribute("selected", Boolean.valueOf(selected).toString()); categoryElement.setAttribute("order", Integer.valueOf(category.getOrder()).toString()); Element categoryKeyElement = doc.createElement("key"); safeAppendTextNode(doc, categoryKeyElement, category.getKey(), false); Element categoryEscapedKeyElement = doc.createElement("escapedKey"); safeAppendTextNode(doc, categoryEscapedKeyElement, Web.escapeJavascript(category.getKey()), false); Element categoryUrlElement = doc.createElement("url"); // Resolve the site_type of the form /portal/category/<siteId>/<categoryKey>/<optionalToolId> safeAppendTextNode(doc, categoryUrlElement, getContext() + "/" + TOOL_CATEGORY + "/" + siteId + "/" + category.getKey(), true); Element categoryHelperUrlElement = doc.createElement("helperUrl"); // Resolve the site_type of the form /portal/category_helper/<siteId>/<categoryKey>/<optionalToolId> safeAppendTextNode(doc, categoryHelperUrlElement, getContext() + "/" + TOOL_CATEGORY_HELPER + "/" + siteId + "/" + category.getKey(), true); categoryElement.appendChild(categoryKeyElement); categoryElement.appendChild(categoryEscapedKeyElement); categoryElement.appendChild(categoryUrlElement); categoryElement.appendChild(categoryHelperUrlElement); if (portalManager.isUseDb()) { appendTextElementNode(doc, "layoutFile", category.getKey(), categoryElement); } else { appendTextElementNode(doc, "layoutFile", getCategoryHomePagePath(category.getHomePagePath()), categoryElement); } Element pagesElement = doc.createElement("pages"); for (Iterator i=categoryPageList.iterator();i.hasNext();) { SitePageWrapper page = (SitePageWrapper) i.next(); pagesElement.appendChild(createPageXml(doc, page.getOrder(), siteId, page.getPage(), category.getKey(), pageId)); } categoryElement.appendChild(pagesElement); return categoryElement; } /** * concatenates categoryBasePath, locale, and homePagePath. If can't resolve this path the locale * portion is removed. * @param homePagePath * @return localized path */ protected String getCategoryHomePagePath(String homePagePath) { ResourceLoader rl = new ResourceLoader(); String localeStr = rl.getLocale().toString(); String localizedPath = categoryBasePath + "_" + localeStr +"/" + homePagePath; try { URL url = getServletContext().getResource(localizedPath); if (url != null) { return localizedPath; } // try without the country part localizedPath = categoryBasePath + "_" + localeStr.replaceFirst("_.*","") +"/" + homePagePath; url = getServletContext().getResource(localizedPath); if (url != null) { return localizedPath; } } catch (MalformedURLException e) { e.printStackTrace(); } return categoryBasePath + "/" + homePagePath; } protected Element createPageXml(Document doc, int index, String siteId, SitePage page, String parentCategoryKey, String pageId) { Element pageElement = doc.createElement("page"); pageElement.setAttribute("order", Integer.valueOf(index).toString()); boolean pageSelected = page.getId().equals(pageId); pageElement.setAttribute("selected", Boolean.valueOf(pageSelected).toString()); pageElement.setAttribute("layout", Integer.valueOf(page.getLayout()).toString()); pageElement.setAttribute("popUp", Boolean.valueOf(page.isPopUp()).toString()); pageElement.setAttribute("toolId", getFirstToolId(page)); Element pageName = doc.createElement("title"); safeAppendTextNode(doc, pageName, page.getTitle(), true); // portal/site/9607661f-f3aa-4938-8005-c3ffaa228c6c/page/0307f10c-225b-4db8-803e-b12f24e38544 Element pageUrl = doc.createElement("url"); if (parentCategoryKey != null && !parentCategoryKey.equals(ToolCategory.UNCATEGORIZED_KEY)) { safeAppendTextNode(doc, pageUrl, getContext() + "/category/" + siteId + "/" + parentCategoryKey + "/" + page.getId(), true); } else { safeAppendTextNode(doc, pageUrl, getContext() + "/site/" + siteId + "/page/" + page.getId(), true); } Element popPageUrl = doc.createElement("popUrl"); safeAppendTextNode(doc, popPageUrl, getContext() + "/page/" + page.getId(), true); Element columns = doc.createElement("columns"); for (int i=0;i<2;i++) { Element column = doc.createElement("column"); column.setAttribute("index", Integer.valueOf(i).toString()); column.appendChild(createColumnToolsXml(doc, page.getTools(i), page)); columns.appendChild(column); } pageElement.appendChild(pageName); pageElement.appendChild(pageUrl); pageElement.appendChild(popPageUrl); pageElement.appendChild(columns); return pageElement; } protected String getFirstToolId(SitePage page) { List tools = page.getTools(); if (tools.size() > 0) { Placement placement = (Placement) tools.get(0); if (placement.getTool() != null) return placement.getTool().getId(); } return ""; } protected Element createColumnToolsXml(Document doc, List tools, SitePage page) { Element toolsElement = doc.createElement("tools"); for (Iterator i=tools.iterator();i.hasNext();) { Placement placement = (Placement) i.next(); if (placement.getTool() != null) toolsElement.appendChild(createToolXml(doc, placement, page)); } return toolsElement; } protected Element createToolXml(Document doc, Placement placement, SitePage page) { Element toolElement = doc.createElement("tool"); Element title = doc.createElement("title"); safeAppendTextNode(doc, title, page.getTitle(), true); Element escapedId = doc.createElement("escapedId"); String id = Web.escapeJavascript("i" + placement.getId()); id = id.substring(1); safeAppendTextNode(doc, escapedId, id, true); //portal/tool/ad222467-e186-4cca-80e9-d12a9d6db392?panel=Main Element toolUrl = doc.createElement("url"); safeAppendTextNode(doc, toolUrl, getContext() + "/tool/" + placement.getId() + "?panel=Main", true); //portal/title/ad222467-e186-4cca-80e9-d12a9d6db392 Element toolTitleUrl = doc.createElement("titleUrl"); safeAppendTextNode(doc, toolTitleUrl, getContext() + "/title/" + placement.getId(), true); toolElement.appendChild(title); toolElement.appendChild(escapedId); toolElement.appendChild(toolUrl); toolElement.appendChild(toolTitleUrl); return toolElement; } protected Element createSiteTypesXml(Document doc, Map siteTypesMap, String siteTypeKey, String siteId) { Element siteTypes = doc.createElement("siteTypes"); List types = new ArrayList(siteTypesMap.keySet()); Collections.sort(types); for (Iterator i=types.iterator();i.hasNext();) { SiteType type = (SiteType)i.next(); boolean selected = type.getKey().equals(siteTypeKey); siteTypes.appendChild(createSiteTypeXml(doc, type, (List)siteTypesMap.get(type), selected, siteId)); } return siteTypes; } protected Element createSiteTypeXml(Document doc, SiteType type, List sites, boolean selected, String siteId) { Element siteTypeElement = doc.createElement("siteType"); siteTypeElement.setAttribute("selected", Boolean.valueOf(selected).toString()); siteTypeElement.setAttribute("order", Integer.valueOf(type.getOrder()).toString()); siteTypeElement.setAttribute("userSite", Boolean.valueOf(type == SiteType.MY_WORKSPACE).toString()); Element siteTypeKey = doc.createElement("key"); safeAppendTextNode(doc, siteTypeKey, type.getKey(), false); siteTypeElement.appendChild(siteTypeKey); Element siteTypeName = doc.createElement("name"); safeAppendTextNode(doc, siteTypeName, type.getName(), false); siteTypeElement.appendChild(siteTypeName); Element siteTypeEscapedKey = doc.createElement("escapedKey"); safeAppendTextNode(doc, siteTypeEscapedKey, Web.escapeJavascript(type.getKey()), false); siteTypeElement.appendChild(siteTypeEscapedKey); Element siteTypeUrl = doc.createElement("url"); // /portal/site_type/<key> try { Site site = getPortalManager().getSite(type.getKey()); safeAppendTextNode(doc, siteTypeUrl, getContext() + "/site/" + type.getKey(), true); } catch (RuntimeException e) { safeAppendTextNode(doc, siteTypeUrl, getContext() + "/" + SITE_TYPE + "/" + type.getKey(), true); } siteTypeElement.appendChild(siteTypeUrl); Element siteTypeHelperUrl = doc.createElement("helperUrl"); // /portal/site_type_helper/<key> safeAppendTextNode(doc, siteTypeHelperUrl, getContext() + "/" + SITE_TYPE_HELPER + "/" + type.getKey(), true); siteTypeElement.appendChild(siteTypeHelperUrl); siteTypeElement.appendChild(createSitesListXml(doc, sites, siteId)); return siteTypeElement; } protected void safeAppendTextNode(Document doc, Element element, String text, boolean cdata) { if (text != null) { element.appendChild(cdata?doc.createCDATASection(text):doc.createTextNode(text)); } } protected Element createSitesListXml(Document doc, List mySites, String siteId) { Session session = SessionManager.getCurrentSession(); int prefTabs = 4; List prefExclude = new Vector(); List prefOrder = new Vector(); if (session.getUserId() != null) { Preferences prefs = PreferencesService.getPreferences(session.getUserId()); ResourceProperties props = prefs.getProperties("sakai.portal.sitenav"); try { prefTabs = (int) props.getLongProperty("tabs"); } catch (Exception any) { } List l = props.getPropertyList("exclude"); if (l != null) { prefExclude = l; } l = props.getPropertyList("order"); if (l != null) { prefOrder = l; } } mySites.removeAll(prefExclude); // re-order mySites to have order first, the rest later List ordered = new Vector(); for (Iterator i = prefOrder.iterator(); i.hasNext();) { String id = (String) i.next(); // find this site in the mySites list int pos = indexOf(id, mySites); if (pos != -1) { // move it from mySites to order Site s = (Site) mySites.get(pos); ordered.add(s); mySites.remove(pos); } } // pick up the rest of the mySites ordered.addAll(mySites); mySites = ordered; Element sitesElement = doc.createElement("sites"); int order = 0; for (Iterator i=mySites.iterator();i.hasNext();) { Site site= (Site) i.next(); boolean selected = siteId != null?site.getId().equals(siteId):false; sitesElement.appendChild(createSiteXml(doc, site, selected, order, false)); order++; } return sitesElement; } protected Element createSiteXml(Document doc, Site site, boolean selected, int order, boolean extra) { Element siteElement = doc.createElement("site"); siteElement.setAttribute("selected", Boolean.valueOf(selected).toString()); siteElement.setAttribute("extra", Boolean.valueOf(extra).toString()); siteElement.setAttribute("published", Boolean.valueOf(site.isPublished()).toString()); siteElement.setAttribute("order", Integer.valueOf(order).toString()); Element siteUrl = doc.createElement("url"); // http://localhost:8080/portal/site/bc5b1aa2-c53b-4fd1-0017-f91eef511e65<key> safeAppendTextNode(doc, siteUrl, getContext() + "/site/" + site.getId(), true); siteElement.appendChild(siteUrl); Element siteTitle = doc.createElement("title"); safeAppendTextNode(doc, siteTitle, site.getTitle(), true); siteElement.appendChild(siteTitle); Element siteDescription = doc.createElement("description"); safeAppendTextNode(doc, siteDescription, site.getDescription(), true); siteElement.appendChild(siteDescription); return siteElement; } protected Element createSkinsXml(Document doc, List skins) { Element skinsElement = doc.createElement("skins"); int index = 0; String skinRepo = ServerConfigurationService.getString("skin.repo"); Element skin = doc.createElement("skin"); skin.setAttribute("order", index + ""); safeAppendTextNode(doc, skin, getContext() + "/library/css/osp-portal.css", true); skinsElement.appendChild(skin); index++; for (Iterator i=skins.iterator();i.hasNext();) { String skinUrl = (String) i.next(); index = appendSkin(skinRepo, skinUrl, doc, index, skinsElement, "/portal.css"); } if (index == 1) { String skinUrl = ServerConfigurationService.getString("skin.default"); index = appendSkin(skinRepo, skinUrl, doc, index, skinsElement, "/portal.css"); } return skinsElement; } protected Element createToolSkinsXml(Document doc, List skins) { Element skinsElement = doc.createElement("toolSkins"); int index = 0; String skinRepo = ServerConfigurationService.getString("skin.repo"); Element skin = doc.createElement("skin"); skin = doc.createElement("skin"); skin.setAttribute("order", index + ""); safeAppendTextNode(doc, skin, getContext() + "/library/skin/tool_base.css", true); skinsElement.appendChild(skin); index++; for (Iterator i=skins.iterator();i.hasNext();) { String skinUrl = (String) i.next(); index = appendSkin(skinRepo, skinUrl, doc, index, skinsElement, "/tool.css"); } if (index == 2) { String skinUrl = ServerConfigurationService.getString("skin.default"); index = appendSkin(skinRepo, skinUrl, doc, index, skinsElement, "/tool.css"); } return skinsElement; } protected int appendSkin(String skinRepo, String skinUrl, Document doc, int index, Element skinsElement, String cssFile) { Element skin; String skinPortalUrl = skinRepo + "/" + skinUrl + cssFile; skin = doc.createElement("skin"); skin.setAttribute("order", index + ""); safeAppendTextNode(doc, skin, skinPortalUrl, true); skinsElement.appendChild(skin); index++; return index; } protected List getSkins(SiteType siteType, Site site) { List skins = new ArrayList(); if (siteType != null && siteType.getSkin() != null) { skins.add(siteType.getSkin()); } if (site != null && site.getSkin() != null) { skins.add(site.getSkin()); } return skins; } protected Element createUserXml(Document doc, User current) { Element user = doc.createElement("currentUser"); appendTextElementNode(doc, "id", current.getId(), user); appendTextElementNode(doc, "first", current.getFirstName(), user); appendTextElementNode(doc, "last", current.getLastName(), user); appendTextElementNode(doc, "email", current.getEmail(), user); return user; } protected Element createLoginXml(Document doc, HttpServletRequest req) { Element login = doc.createElement("loginInfo"); String logInOutUrl = Web.serverUrl(req); String loginText = null; String logoutText = null; String image1 = null; // for a possible second link String logInOutUrl2 = null; String loginText2 = null; String image2 = null; boolean topLogin = ServerConfigurationService.getBoolean("top.login", true); boolean containerLogin = ServerConfigurationService.getBoolean("container.login", false); if (containerLogin) topLogin = false; if (!topLogin) { logInOutUrl += getPortalString() + "/login"; // let the login url be overridden by configuration String overrideLoginUrl = StringUtils .trimToNull(ServerConfigurationService .getString("login.url")); if (overrideLoginUrl != null) logInOutUrl = overrideLoginUrl; // check for a login text override loginText = StringUtils.trimToNull(ServerConfigurationService .getString("login.text")); if (loginText == null) loginText = rbsitenav.getString("log.login"); // check for an image for the login image1 = StringUtils.trimToNull(ServerConfigurationService .getString("login.icon")); // check for a possible second, xlogin link if (Boolean.TRUE.toString().equalsIgnoreCase( ServerConfigurationService.getString("xlogin.enabled"))) { // get the text and image as configured loginText2 = StringUtils.trimToNull(ServerConfigurationService .getString("xlogin.text")); image2 = StringUtils.trimToNull(ServerConfigurationService .getString("xlogin.icon")); logInOutUrl2 = ServerConfigurationService .getString("portalPath") + "/xlogin"; appendTextElementNode(doc, "logInOutUrl2", logInOutUrl2, login); appendTextElementNode(doc, "loginText2", loginText2, login); appendTextElementNode(doc, "image2", image2, login); } } // check for a logout text override logoutText = StringUtils.trimToNull(ServerConfigurationService .getString("logout.text")); if (logoutText == null) logoutText = rbsitenav.getString("sit_log"); appendTextElementNode(doc, "topLogin", Boolean.toString(topLogin), login); appendTextElementNode(doc, "logInOutUrl", logInOutUrl, login); appendTextElementNode(doc, "loginText", loginText, login); appendTextElementNode(doc, "logoutText", logoutText, login); appendTextElementNode(doc, "image1", image1, login); return login; } protected String checkVisitSite(String siteId, Session session, HttpServletRequest req, HttpServletResponse res) throws IOException, ToolException { // default site if not set if (siteId == null) { if (session.getUserId() == null) { siteId = ServerConfigurationService.getGatewaySiteId(); } else { siteId = SiteService.getUserSiteId(session.getUserId()); } } // find the site, for visiting Site site = null; try { site = getSiteVisit(siteId); } catch (IdUnusedException e) { doError(req, res, session, ERROR_SITE); return null; } catch (PermissionException e) { // if not logged in, give them a chance if (session.getUserId() == null) { doLogin(req, res, session, req.getPathInfo(), false); } else { doError(req, res, session, ERROR_SITE); } return null; } return site.getId(); } public void init(ServletConfig config) throws ServletException { super.init(config); setPortalManager((PortalManager) ComponentManager.get(PortalManager.class.getName() + ".tx")); try { setDocumentBuilder(DocumentBuilderFactory.newInstance().newDocumentBuilder()); String transformPath = config.getInitParameter("transform"); Templates templates = createTemplate(config, transformPath); setTemplates(templates); String transformToolCategoryPath = config.getInitParameter("transformToolCategory"); Templates templatesToolCategory = createTemplate(config, transformToolCategoryPath); setServletResolver(new PortalResourceUriResolver(getPortalManager(), config.getServletContext())); setToolCategoryTemplates(templatesToolCategory); categoryBasePath = config.getInitParameter("categoryBasePath"); if (categoryBasePath == null || categoryBasePath.length() == 0) { categoryBasePath = "/WEB-INF/category"; } Collection categoriesNeedingLoading = getPortalManager().getCategoriesInNeedOfFiles(); if (categoriesNeedingLoading != null) { for (Iterator<ToolCategory> i=categoriesNeedingLoading.iterator();i.hasNext();) { processCategoryFiles(i.next(), config.getServletContext()); } getPortalManager().saveToolCategories(categoriesNeedingLoading); } } catch (ParserConfigurationException e) { throw new ServletException(e); } catch (TransformerConfigurationException e) { throw new ServletException(e); } catch (MalformedURLException e) { throw new ServletException(e); } catch (IOException e) { throw new ServletException(e); } } protected void processCategoryFiles(ToolCategory toolCategory, ServletContext context) throws IOException { File base = new File(categoryBasePath); String parentPath = base.getParent(); Set paths = context.getResourcePaths(parentPath); for (Iterator<String> i=paths.iterator();i.hasNext();) { String path = i.next(); if (path.startsWith(categoryBasePath)) { path += toolCategory.getHomePagePath(); if (context.getResource(path) != null) { processCategoryFile(toolCategory, path, context.getResourceAsStream(path)); } } } } protected void processCategoryFile(ToolCategory toolCategory, String path, InputStream is) throws IOException { String locale = path.substring(categoryBasePath.length()); locale = locale.substring(0, locale.length() - toolCategory.getHomePagePath().length() - 1); if (locale.startsWith("_")) { locale = locale.substring(1); } ByteArrayOutputStream bos = new ByteArrayOutputStream(); int c = is.read(); while (c != -1) { bos.write(c); c = is.read(); } bos.flush(); toolCategory.getPages().put(locale, bos.toByteArray()); } private Templates createTemplate(ServletConfig config, String transformPath) throws MalformedURLException, TransformerConfigurationException { InputStream stream = config.getServletContext().getResourceAsStream( transformPath); URL url = config.getServletContext().getResource(transformPath); String urlPath = url.toString(); String systemId = urlPath.substring(0, urlPath.lastIndexOf('/') + 1); Templates templates = TransformerFactory.newInstance().newTemplates( new StreamSource(stream, systemId)); return templates; } public PortalManager getPortalManager() { return portalManager; } public void setPortalManager(PortalManager portalManager) { this.portalManager = portalManager; } protected String getContext() { return "/" + this.getServletContext().getServletContextName(); } public DocumentBuilder getDocumentBuilder() { return documentBuilder; } public void setDocumentBuilder(DocumentBuilder documentBuilder) { this.documentBuilder = documentBuilder; } protected Transformer getToolCategoryTransformer() { try { Transformer trans = getToolCategoryTemplates().newTransformer(); trans.setURIResolver(getServletResolver()); return trans; } catch (TransformerConfigurationException e) { throw new RuntimeException(e); } } public Transformer getTransformer() { try { Transformer trans = getTemplates().newTransformer(); trans.setURIResolver(getServletResolver()); return trans; } catch (TransformerConfigurationException e) { throw new RuntimeException(e); } } public Templates getTemplates() { return templates; } public void setTemplates(Templates templates) { this.templates = templates; } public Templates getToolCategoryTemplates() { return toolCategoryTemplates; } public void setToolCategoryTemplates(Templates toolCategoryTemplates) { this.toolCategoryTemplates = toolCategoryTemplates; } public URIResolver getServletResolver() { return servletResolver; } public void setServletResolver(URIResolver servletResolver) { this.servletResolver = servletResolver; } protected void dumpDocument(Node node) { try { Transformer transformer = TransformerFactory.newInstance().newTransformer(); transformer.setOutputProperty( OutputKeys.INDENT, "yes" ); transformer.transform( new DOMSource(node), new StreamResult(System.out) ); } catch ( Exception e ) { e.printStackTrace(); } } }