/**********************************************************************************
* $URL: https://source.sakaiproject.org/svn/portal/trunk/portal-render-engine-impl/impl/src/java/org/sakaiproject/portal/charon/velocity/VelocityPortalRenderEngine.java $
* $Id: VelocityPortalRenderEngine.java 132676 2013-12-17 17:01:38Z 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.velocity;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.runtime.RuntimeConstants;
import org.sakaiproject.component.api.ServerConfigurationService;
import org.sakaiproject.portal.api.PortalRenderContext;
import org.sakaiproject.portal.api.PortalRenderEngine;
import org.sakaiproject.portal.api.PortalService;
import org.sakaiproject.portal.api.StyleAbleProvider;
import org.sakaiproject.tool.api.Placement;
import org.sakaiproject.tool.api.SessionManager;
/**
* A velocity render engine adapter
*
* @author ieb
* @since Sakai 2.4
* @version $Rev: 132676 $
*/
public class VelocityPortalRenderEngine implements PortalRenderEngine
{
private static final Log log = LogFactory.getLog(VelocityPortalRenderEngine.class);
private VelocityEngine vengine;
private boolean debug = false;
private List<Map<String, String>> availablePortalSkins;
private ServletContext context;
private String defaultSkin = "neoskin";
private boolean styleAble = false;
private boolean styleAbleContentSummary = false;
private PortalService portalService;
private ServerConfigurationService serverConfigurationService;
private SessionManager sessionManager;
private String portalConfig = "portalvelocity.config";
public void init() throws Exception
{
if (log.isTraceEnabled()) {
debug = true;
}
try
{
styleAble = serverConfigurationService.getBoolean("portal.styleable", false);
styleAbleContentSummary = serverConfigurationService.getBoolean(
"portal.styleable.contentSummary", false);
defaultSkin = serverConfigurationService.getString("portal.templates", "neoskin");
}
catch (Exception ex)
{
log
.warn("No Server configuration service available, assuming default settings ");
}
if ( sessionManager == null ) {
log.warn("No session Manager, assuming test mode ");
}
vengine = new VelocityEngine();
vengine.setApplicationAttribute(ServletContext.class.getName(), context);
vengine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM_CLASS,
"org.apache.velocity.runtime.log.SimpleLog4JLogSystem");
vengine.setProperty("runtime.log.logsystem.log4j.category", "ve.portal");
Properties p = new Properties();
InputStream in = null;
try {
in = this.getClass().getResourceAsStream(portalConfig );
if ( in == null ) {
throw new RuntimeException("Unable to load configuration "+portalConfig);
} else {
log.info("Loaded "+portalConfig);
}
p.load(in);
vengine.init(p);
availablePortalSkins = new ArrayList<Map<String, String>>();
Map<String, String> m = new HashMap<String, String>();
m.put("name", defaultSkin);
m.put("display", "Default");
availablePortalSkins.add(m);
/*
* m = new HashMap(); m.put("name", "skintwo"); m.put("display", "Skin
* Two"); availablePortalSkins.add(m);
*/
vengine.getTemplate("/vm/"+defaultSkin+"/macros.vm");
}
catch (IOException e) {
throw new RuntimeException("Exception encounterd: " + e, e);
}
finally {
if (in != null) {
try {
in.close();
} catch (IOException e) {
//not much to do
}
}
}
}
public PortalRenderContext newRenderContext(HttpServletRequest request)
{
VelocityPortalRenderContext rc = new VelocityPortalRenderContext();
rc.setRenderEngine(this);
rc.setDebug(debug);
// this is just for testing, it should be in the path or portal to
// ensure that the skin remains.
rc.put("pageSkins", availablePortalSkins);
rc.put("styleableStyleSheet", generateStyleAbleStyleSheet());
rc.put("styleableJS", generateStyleAbleJavaScript());
rc.put("styleable", styleAble);
String portalSkin = defaultSkin;
if (request != null)
{
HttpSession session = request.getSession();
portalSkin = (String) session.getAttribute("portalskin");
String newPortalSkin = request.getParameter("portalskin");
if (newPortalSkin != null && newPortalSkin.length() > 0)
{
session.setAttribute("portalskin", newPortalSkin);
portalSkin = newPortalSkin;
log.debug("Set Skin To " + portalSkin);
}
else
{
if (portalSkin == null || portalSkin.length() == 0)
{
portalSkin = defaultSkin;
session.setAttribute("portalskin", portalSkin);
}
}
rc.put("pageCurrentSkin", portalSkin);
log.debug("Current Skin is " + portalSkin);
}
else
{
log.debug("No Request Object Skin is default");
rc.put("pageCurrentSkin", defaultSkin);
}
InputStream stream = null;
try
{
Properties p = new Properties();
stream = this.getClass().getResourceAsStream(
"/" + portalSkin + "/options.config");
p.load(stream);
rc.setOptions(p);
}
catch (Exception ex)
{
log.info("No options loaded ", ex);
}
finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
//not much to do in this case
}
}
}
return rc;
}
public void render(String template, PortalRenderContext rcontext, Writer out)
throws Exception
{
if (log.isTraceEnabled()) {
log.trace("Portal trace is on, dumping PortalRenderContext to log:\n" + rcontext.dump());
}
Context vc = ((VelocityPortalRenderContext) rcontext).getVelocityContext();
String skin = (String) vc.get("pageCurrentSkin");
if (skin == null || skin.length() == 0)
{
skin = defaultSkin;
}
if (!defaultSkin.equals(skin))
{
vengine.getTemplate("/vm/" + skin + "/macros.vm");
}
vengine.mergeTemplate("/vm/" + skin + "/" + template + ".vm",
((VelocityPortalRenderContext) rcontext).getVelocityContext(), out);
}
private String generateStyleAbleStyleSheet()
{
if (styleAble)
{
StyleAbleProvider sp = portalService.getStylableService();
if (sp != null)
{
String userId = getCurrentUserId();
try
{
return sp.generateStyleSheet(userId);
// ca.utoronto.atrc.transformable.common.prefs.Preferences
// prefsForUser = TransformAblePrefsService
// .getTransformAblePreferences(userId);
// return StyleAbleService.generateStyleSheet(prefsForUser);
}
catch (Exception e)
{
return null;
}
}
}
return null;
}
/**
* @return null if no JavaScript is needed
*/
private String generateStyleAbleJavaScript()
{
// Enable / disable StyleAble javascript based on property flag.
if (styleAble && styleAbleContentSummary)
{
StyleAbleProvider sp = portalService.getStylableService();
if (sp != null)
{
String userId = getCurrentUserId();
try
{
return sp.generateJavaScript(userId);
// ca.utoronto.atrc.transformable.common.prefs.Preferences
// prefsForUser = TransformAblePrefsService
// .getTransformAblePreferences(userId);
// return StyleAbleService.generateJavaScript(prefsForUser);
}
catch (Exception e)
{
return null;
}
}
}
return null;
}
private String getCurrentUserId()
{
if ( sessionManager == null ) {
return "test-mode-user";
} else {
return sessionManager.getCurrentSession().getUserId();
}
}
public boolean isDebug()
{
return debug;
}
public void setDebug(boolean debug)
{
this.debug = debug;
}
/**
* @return the context
*/
public ServletContext getContext()
{
return context;
}
/**
* @param context
* the context to set
*/
public void setContext(ServletContext context)
{
this.context = context;
}
/*
* (non-Javadoc)
*
* @see org.sakaiproject.portal.api.PortalRenderEngine#setupForward(javax.servlet.http.HttpServletRequest,
* javax.servlet.http.HttpServletResponse,
* org.sakaiproject.tool.api.Placement, java.lang.String)
*/
public void setupForward(HttpServletRequest req, HttpServletResponse res,
Placement p, String skin)
{
String headJs = (String) req.getAttribute("sakai.html.head.js");
String headCssToolBase = (String) req.getAttribute("sakai.html.head.css.base");
String headCssToolSkin = (String) req.getAttribute("sakai.html.head.css.skin");
String bodyonload = (String) req.getAttribute("sakai.html.body.onload");
String customUserCss = generateStyleAbleStyleSheet();
if (customUserCss != null)
{
customUserCss = "<style type=\"text/css\" title=\"StyleAble\">\n"
+ customUserCss + "</style>\n";
}
else
{
customUserCss = "";
}
String styleAbleJs = generateStyleAbleJavaScript();
if (styleAbleJs != null)
{
styleAbleJs = "<script "
+ "type=\"text/javascript\" language=\"JavaScript\">\n" + styleAbleJs
+ "\n</script>\n";
headJs = headJs + styleAbleJs;
bodyonload = bodyonload + "styleableonload();";
}
headCssToolSkin = headCssToolSkin + customUserCss;
String headCss = headCssToolBase + headCssToolSkin + customUserCss;
String head = headCss + headJs;
req.setAttribute("sakai.html.head", head);
req.setAttribute("sakai.html.head.css", headCss);
req.setAttribute("sakai.html.head.js", headJs);
req.setAttribute("sakai.html.head.css.base", headCssToolBase);
req.setAttribute("sakai.html.head.css.skin", headCssToolSkin);
req.setAttribute("sakai.html.body.onload", bodyonload);
}
/**
* @return the stylable
*/
public boolean isStyleAble()
{
return styleAble;
}
/**
* @param stylable
* the stylable to set
*/
public void setStyleAble(boolean styleAble)
{
this.styleAble = styleAble;
}
/**
* @param instance
*/
public void setPortalService(PortalService instance)
{
this.portalService = instance;
}
/**
* @return the serverConfigurationService
*/
public ServerConfigurationService getServerConfigurationService()
{
return serverConfigurationService;
}
/**
* @param serverConfigurationService
* the serverConfigurationService to set
*/
public void setServerConfigurationService(
ServerConfigurationService serverConfigurationService)
{
this.serverConfigurationService = serverConfigurationService;
}
/**
* @return the sessionManager
*/
public SessionManager getSessionManager()
{
return sessionManager;
}
/**
* @param sessionManager the sessionManager to set
*/
public void setSessionManager(SessionManager sessionManager)
{
this.sessionManager = sessionManager;
}
/**
* @return the portalConfig
*/
public String getPortalConfig()
{
return portalConfig;
}
/**
* @param portalConfig the portalConfig to set
*/
public void setPortalConfig(String portalConfig)
{
this.portalConfig = portalConfig;
}
}