/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/portal/trunk/portal-render-engine-impl/pack/src/test/org/sakaiproject/portal/charon/test/MockCharonPortal.java $
* $Id: MockCharonPortal.java 132920 2013-12-26 17:29:01Z csev@umich.edu $
***********************************************************************************
*
* Copyright (c) 2005, 2006, 2007, 2008 The Sakai Foundation
*
* Licensed under the Educational Community License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.opensource.org/licenses/ECL-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
**********************************************************************************/
package org.sakaiproject.portal.charon.test;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpServlet;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.sakaiproject.portal.api.PortalRenderContext;
import org.sakaiproject.portal.charon.velocity.VelocityPortalRenderEngine;
import org.w3c.tidy.Tidy;
/**
* <p>
* This class operates as Mock portal to enable testing of a set of templates.
* It can be used to drive any render engine, but is setup for the default
* render engine. It is run as a unit test.
* </p>
*/
public class MockCharonPortal extends HttpServlet
{
/** Our log (commons). */
private static Log log = LogFactory.getLog(MockCharonPortal.class);
private VelocityPortalRenderEngine rengine;
private File outputDir;
private String outputFile;
private Object resourceLoader;
public MockCharonPortal(File outputDir) throws Exception
{
this.outputDir = outputDir;
String renderEngineClass = VelocityPortalRenderEngine.class.getName();
Class c = Class.forName(renderEngineClass);
rengine = (VelocityPortalRenderEngine) c.newInstance();
rengine.setPortalConfig("/testportalvelocity.config");
rengine.setDebug(true);
rengine.init();
}
public void doError(boolean withSession, boolean withToolSession) throws IOException
{
// start the response
PortalRenderContext rcontext = startPageContext();
if ( withSession ) {
rcontext.put("s", new MockSession());
}
if ( withToolSession ) {
rcontext.put("ts", new MockToolSession());
}
rcontext.put("req", new MockHttpServletRequest());
showSession(rcontext);
showSnoop(rcontext);
sendResponse(rcontext, "error");
}
private void showSnoop(PortalRenderContext rcontext)
{
rcontext.put("snoopRequest", "snoopRequest");
Map m = new HashMap();
m.put("param1", "configparam1");
m.put("param1", "configparam1");
rcontext.put("snoopServletConfigParams", m);
rcontext.put("snoopRequest", "snoopRequest");
rcontext.put("snoopRequestHeaders", m);
rcontext.put("snoopRequestParamsSingle", m);
rcontext.put("snoopRequestParamsMulti", m);
rcontext.put("snoopRequestAttr", m);
}
public void doGallery() throws IOException
{
PortalRenderContext rcontext = startPageContext();
// the 'little' top area
includeGalleryNav(rcontext);
includeWorksite(rcontext);
includeBottom(rcontext);
sendResponse(rcontext, "gallery");
}
public void doNavLogin() throws IOException
{
// start the response
PortalRenderContext rcontext = startPageContext();
includeLogo(rcontext);
sendResponse(rcontext, "login");
}
public void doPage() throws IOException
{
PortalRenderContext rcontext = startPageContext();
includePage(rcontext);
includeBottom(rcontext);
sendResponse(rcontext, "page");
}
private PortalRenderContext startPageContext()
{
PortalRenderContext rcontext = rengine.newRenderContext(null);
rcontext.put("pageSkinRepo", "skinRepo");
rcontext.put("pageSkin", "skin");
rcontext.put("pageTitle", "Web.escapeHtml(title)");
rcontext.put("pageScriptPath", "getScriptPath()");
rcontext.put("pageTop", Boolean.valueOf(true));
rcontext.put("pageSiteType", "class=\"siteType\" ");
rcontext.put("toolParamResetState", "PARM_STATE_RESET");
rcontext.put("rloader", resourceLoader);
String headCssToolBase = "<link href=\""
+ "/tool_base.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />\n";
String headCssToolSkin = "<link href=\""
+ "/tool.css\" type=\"text/css\" rel=\"stylesheet\" media=\"all\" />\n";
String headCss = headCssToolBase + headCssToolSkin;
String headJs = "<script type=\"text/javascript\" src=\"/library/js/headscripts.js\"></script>\n";
String head = headCss + headJs;
rcontext.put("sakai_html_head", head);
rcontext.put("sakai_html_head_css", headCss);
rcontext.put("sakai_html_head_css_base", headCssToolBase);
rcontext.put("sakai_html_head_css_skin", headCssToolSkin);
rcontext.put("sakai_html_head_js", headJs);
rcontext.put("sitReset", "sitReset");
//rcontext.put("browser", new BrowserDetector("Mozilla/5.0 (Macintosh; U; Intel Mac OS X; en) AppleWebKit/523.12.2 (KHTML, like Gecko) Version/3.0.4 Safari/523.12.2"));
return rcontext;
}
public void doSite() throws IOException
{
PortalRenderContext rcontext = startPageContext();
// the 'full' top area
includeSiteNav(rcontext);
includeWorksite(rcontext);
includeBottom(rcontext);
// end the response
sendResponse(rcontext, "site");
}
public void doWorksite() throws IOException
{
PortalRenderContext rcontext = startPageContext();
includeWorksite(rcontext);
includeBottom(rcontext);
// end the response
sendResponse(rcontext, "worksite");
}
protected void includeBottom(PortalRenderContext rcontext)
{
rcontext.put("pagepopup", false);
{
List l = new ArrayList();
l.add("bottomnav1");
l.add("bottomnav2");
rcontext.put("bottomNav", l);
}
rcontext.put("bottomNavSitNewWindow", "site_newwindow");
{
List l = new ArrayList();
Map m = new HashMap();
m.put("poweredByUrl", "poweredByUrl[i]");
m.put("poweredByImage", "poweredByImage[i]");
m.put("poweredByAltText", "poweredByAltText[i]");
l.add(m);
rcontext.put("bottomNavPoweredBy", l);
}
{
List l = new ArrayList();
Map m = new HashMap();
m.put("poweredByUrl", "http://sakaiproject.org");
m.put("poweredByImage", "/library/image/sakai_powered.gif");
m.put("poweredByAltText", "Powered by Sakai");
l.add(m);
rcontext.put("bottomNavPoweredBy", l);
}
rcontext.put("bottomNavService", "service");
rcontext.put("bottomNavCopyright", "copyright");
rcontext.put("bottomNavServiceVersion", "serviceVersion");
rcontext.put("bottomNavSakaiVersion", "sakaiVersion");
rcontext.put("bottomNavServer", "server");
}
protected void includeGalleryLogin(PortalRenderContext rcontext) throws IOException
{
includeLogin(rcontext);
}
protected void includeGalleryNav(PortalRenderContext rcontext) throws IOException
{
rcontext.put("galleryHasAccessibilityURL", Boolean.valueOf(true));
rcontext.put("galleryAccessibilityURL", "accessibilityURL");
// rcontext.put("gallarySitAccessibility", "sit_accessibility");
// rcontext.put("gallarySitJumpcontent", "sit_jumpcontent");
// rcontext.put("gallarySitJumptools", "sit_jumptools");
// rcontext.put("gallarySitJumpworksite", "sit_jumpworksite");
rcontext.put("gallaryLoggedIn", Boolean.valueOf(true));
includeTabs(rcontext);
}
protected void includeLogo(PortalRenderContext rcontext) throws IOException
{
rcontext.put("logoSkin", "skin");
rcontext.put("logoSkinRepo", "skinRepo");
rcontext.put("logoSiteType", "siteType");
rcontext.put("logoSiteClass", "cssClass");
includeLogin(rcontext);
}
protected void includeLogin(PortalRenderContext rcontext)
{
rcontext.put("loginTopLogin", Boolean.valueOf(true));
rcontext.put("loginLogInOutUrl", "logInOutUrl");
rcontext.put("loginMessage", "message");
rcontext.put("loginImage1", "image1");
rcontext.put("loginHasImage1", Boolean.valueOf(true));
rcontext.put("loginLogInOutUrl2", "logInOutUrl2");
rcontext.put("loginHasLogInOutUrl2", Boolean.valueOf(true));
rcontext.put("loginMessage2", "message2");
rcontext.put("loginImage2", "image2");
rcontext.put("loginHasImage2", Boolean.valueOf(true));
rcontext.put("loginPortalPath", "portalPath");
rcontext.put("loginEidWording", "eidWording");
rcontext.put("loginPwWording", "pwWording");
rcontext.put("loginWording", "loginWording");
}
protected void includePage(PortalRenderContext rcontext) throws IOException
{
// divs to wrap the tools
rcontext.put("pageWrapperClass", "wrapperClass");
rcontext.put("pageColumnLayout", "col1of2");
{
List toolList = new ArrayList();
toolList.add(includeTool());
toolList.add(includeTool());
rcontext.put("pageColumn0Tools", toolList);
}
rcontext.put("pageTwoColumn", Boolean.valueOf(true));
{
List toolList = new ArrayList();
toolList.add(includeTool());
rcontext.put("pageColumn1Tools", toolList);
}
}
protected void includePageNav(Map rcontext) throws IOException
{
rcontext.put("pageNavPublished", Boolean.valueOf(true));
rcontext.put("pageNavType", "type");
rcontext.put("pageNavIconUrl", "iconUrl");
rcontext.put("helpMenuClass", "HelpMenuClass");
// rcontext.put("pageNavSitToolsHead", "sit_toolshead");
List l = new ArrayList();
Map m = new HashMap();
m.put("current", Boolean.valueOf(true));
m.put("ispopup", Boolean.valueOf(false));
m.put("pagePopupUrl", "pagePopupUrl");
m.put("pageIdWeb", "pageId");
m.put("jsPageTitle", "pageTitleJS");
m.put("htmlPageTitle", "pageTitleHTML");
m.put("pagerefUrl", "pagerefUrl");
l.add(m);
m.put("current", Boolean.valueOf(false));
m.put("ispopup", Boolean.valueOf(false));
m.put("pagePopupUrl", "pagePopupUrl");
m.put("pageIdWeb", "pageId");
m.put("jsPageTitle", "pageTitleJS");
m.put("htmlPageTitle", "pageTitleHTML");
m.put("pagerefUrl", "pagerefUrl");
m.put("menuClass", "MenuClass");
m.put("pageRefUrl", "pageRefURL");
m.put("pageSiteRefURL", "siteRefURL");
m.put("pageTitle","pageTitle");
l.add(m);
rcontext.put("pageNavTools", l);
rcontext.put("pageNavShowHelp", Boolean.valueOf(true));
rcontext.put("pageNavHelpUrl", "helpUrl");
// rcontext.put("pageNavSitHelp", "sit_help");
// rcontext.put("pageNavSitPresenceTitle", "sit_presencetitle");
// rcontext.put("pageNavSitPresenceFrameTitle",
// "sit_presenceiframetit");
rcontext.put("pageNavToolsCount", l.size());
rcontext.put("pageNavShowPresenceLoggedIn", Boolean.valueOf(true));
rcontext.put("pageNavPresenceUrl", "presenceUrl");
rcontext.put("pageNavPresenceIframe", Boolean.valueOf(false));
rcontext.put("sakaiPresenceTimeDelay", Integer.valueOf(3000));
// rcontext.put("pageNavSitContentshead", "sit_contentshead");
}
protected void includeSiteNav(PortalRenderContext rcontext) throws IOException
{
rcontext.put("siteNavHasAccessibilityURL", Boolean.valueOf((true)));
rcontext.put("siteNavAccessibilityURL", "accessibilityURL");
// rcontext.put("siteNavSitAccessability", "sit_accessibility");
// rcontext.put("siteNavSitJumpContent", "sit_jumpcontent");
// rcontext.put("siteNavSitJumpTools", "sit_jumptools");
// rcontext.put("siteNavSitJumpWorksite", "sit_jumpworksite");
rcontext.put("siteNavLoggedIn", Boolean.valueOf(true));
includeLogo(rcontext);
includeTabs(rcontext);
}
protected void includeTabs(PortalRenderContext rcontext) throws IOException
{
rcontext.put("tabsCssClass", "cssClass");
// rcontext.put("tabsSitWorksiteHead", "sit_worksiteshead");
rcontext.put("tabsCurMyWorkspace", Boolean.valueOf(true));
// rcontext.put("tabsSitMyWorkspace", "sit_mywor");
rcontext.put("tabsSiteUrl", "mySiteUrl");
// rcontext.put("tabsSitWorksite", "sit_worksite");
List l = new ArrayList();
{
Map m = new HashMap();
m.put("isCurrentSite", Boolean.valueOf(false));
m.put("siteTitle", "siteTitle");
m.put("siteUrl", "Web.escapeHtml(s.getTitle())");
l.add(m);
l.add(m);
}
rcontext.put("tabsSites", l);
rcontext.put("tabsHasExtraTitle", Boolean.valueOf(true));
rcontext.put("tabsExtraTitle", "Web.escapeHtml(extraTitle)");
rcontext.put("tabsMoreSitesShow", Boolean.valueOf(true));
// rcontext.put("tabsSitSelectMessage", "sit_selectmessage");
// rcontext.put("tabsSitMode", "sit_more");
{
Map m = new HashMap();
m.put("siteTitle", "Web.escapeHtml(s.getTitle())");
m.put("siteUrl", "siteUrl");
l.add(m);
l.add(m);
}
rcontext.put("tabsMoreSites", l);
rcontext.put("tabsAddLogout", Boolean.valueOf(true));
rcontext.put("tabsLogoutUrl", "logoutUrl");
// rcontext.put("tabsSitLog", "sit_log");
}
protected Map includeTool() throws IOException
{
Map toolMap = new HashMap();
toolMap.put("toolUrl", "toolUrl");
toolMap.put("toolPlacementIDJS", "Main_" + System.currentTimeMillis());
toolMap.put("toolTitle", "titleString");
toolMap.put("toolShowResetButton", Boolean.valueOf(true));
toolMap.put("toolShowHelpButton", Boolean.valueOf(true));
toolMap.put("toolHelpActionUrl", "helpActionUrl");
toolMap.put("toolResetActionUrl", "toolResetActionUrl");
return toolMap;
}
protected void includeWorksite(PortalRenderContext rcontext) throws IOException
{
Map sitePages = new HashMap();
rcontext.put("sitePages", sitePages);
// add the page navigation with presence
includePageNav(sitePages);
// add the page
includePage(rcontext);
}
/**
* Output some session information
*
* @param rcontext
* The print writer
* @param html
* If true, output in HTML, else in text.
*/
protected void showSession(PortalRenderContext rcontext)
{
rcontext.put("sessionSession", "s");
rcontext.put("sessionToolSession", "ts");
}
protected void sendResponse(PortalRenderContext rcontext, String template)
throws IOException
{
// get the writer
if ( outputFile == null ) {
outputFile = template;
}
File htmlOut = new File(outputDir,outputFile+".html");
File tidyOut = new File(outputDir,outputFile+".html.tidy.txt");
File errorFile = new File(outputDir,outputFile+".html.tidy.err");
FileWriter f = new FileWriter(htmlOut);
try
{
log.info("Rendering " + rcontext + " to " + htmlOut);
rengine.render(template, rcontext, f);
}
catch (Exception e)
{
throw new RuntimeException("Failed to render template ", e);
}
f.close();
Tidy t = new Tidy();
FileOutputStream fo = new FileOutputStream(tidyOut);
t.setIndentContent(true);
t.setXHTML(true);
PrintWriter errorOut = new PrintWriter(new FileWriter(errorFile));
t.setErrout(errorOut);
t.setOnlyErrors(false);
t.setQuiet(false);
t.setShowWarnings(true);
t.parse(new FileInputStream(htmlOut), fo);
int e = t.getParseErrors();
int w = t.getParseWarnings();
errorOut.close();
// JTidy r938 became more agressive about warnings
// if ( e != 0 || w != 0 ) {
if ( e != 0 ) {
log.info("Context Dump is " + rcontext.dump());
throw new RuntimeException("Error in HTML see "+errorFile);
}
log.info("All OK");
}
/**
* @return the outputFile
*/
public String getOutputFile()
{
return outputFile;
}
/**
* @param outputFile the outputFile to set
*/
public void setOutputFile(String outputFile)
{
this.outputFile = outputFile;
}
/**
* @return the resourceLoader
*/
public Object getResourceLoader()
{
return resourceLoader;
}
/**
* @param resourceLoader the resourceLoader to set
*/
public void setResourceLoader(Object resourceLoader)
{
this.resourceLoader = resourceLoader;
}
}