/**
* Copyright 2004 Custine Technology Group, Inc.
*
* User: ccustine
* Date: Aug 7, 2004
* Time: 6:09:54 PM
*/
package com.opensymphony.webwork.portlet.dispatcher;
import com.opensymphony.webwork.ServletActionContext;
import com.opensymphony.webwork.WebWorkStatics;
import com.opensymphony.webwork.util.AttributeMap;
import com.opensymphony.webwork.views.velocity.VelocityManager;
import com.opensymphony.xwork.ActionContext;
import com.opensymphony.xwork.ActionProxy;
import com.opensymphony.xwork.ActionProxyFactory;
import com.opensymphony.xwork.config.ConfigurationException;
import com.opensymphony.xwork.config.ConfigurationManager;
import com.opensymphony.xwork.config.providers.XmlConfigurationProvider;
import com.opensymphony.xwork.interceptor.component.ComponentConfiguration;
import com.opensymphony.xwork.interceptor.component.ComponentInterceptor;
import com.opensymphony.xwork.interceptor.component.ComponentManager;
import com.opensymphony.xwork.interceptor.component.DefaultComponentManager;
import com.opensymphony.xwork.util.LocalizedTextUtil;
import net.sf.cglib.proxy.Enhancer;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.event.LoadEvent;
import org.hibernate.event.LoadEventListener;
import org.hibernate.event.def.DefaultLoadEventListener;
import org.hibernate.proxy.HibernateProxy;
import javax.portlet.*;
import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class PortletDispatcher extends GenericPortlet implements WebWorkStatics
{
protected static final Log log = LogFactory.getLog(PortletDispatcher.class);
private static final String PORTLET_DISPATCHER = "com.opensymphony.webwork.portlet.dispatcher.PortletDispatcher";
public static final String ACTION_CONTEXT = "com.opensymphony.webwork.portlet.ActionContext";
public static HashMap createContextMap(Map requestMap, Map parameterMap,
Map sessionMap, Map applicationMap, PortletRequest request,
PortletResponse response, PortletConfig portletConfig)
{
HashMap extraContext = new HashMap();
extraContext.put(ActionContext.PARAMETERS, parameterMap);
extraContext.put(ActionContext.SESSION, sessionMap);
extraContext.put(ActionContext.APPLICATION, applicationMap);
extraContext.put(ActionContext.LOCALE, request.getLocale());
extraContext.put(HTTP_REQUEST, request);
extraContext.put(HTTP_RESPONSE, response);
extraContext.put(SERVLET_CONFIG, portletConfig);
extraContext.put(ComponentInterceptor.COMPONENT_MANAGER, request
.getAttribute(ComponentManager.COMPONENT_MANAGER_KEY));
// helpers to get access to request/session/application scope
extraContext.put("request", requestMap);
extraContext.put("session", sessionMap);
extraContext.put("application", applicationMap);
extraContext.put("parameters", parameterMap);
AttributeMap attrMap = new AttributeMap(extraContext);
extraContext.put("attr", attrMap);
return extraContext;
}
public void init(PortletConfig config) throws PortletException
{
log.debug("Initializing portlet"
+ config.getPortletContext().getPortletContextName() + "::"
+ config.getPortletName());
super.init(config);
String xworkConfig = (String) config.getInitParameter("xwork-config");
if (xworkConfig != null)
{
log.debug("Loading xwork config file " + xworkConfig
+ " for portlet " + config.getPortletName());
ConfigurationManager
.addConfigurationProvider(new XmlConfigurationProvider(
xworkConfig));
}
// This init mothod requires a modification to VelocityManager to accept
// the PortletContext
// I think this is dependent on WebWork CVS or a recent release
//TODO
//VelocityManager.getInstance().init(config.getPortletContext());
LocalizedTextUtil
.addDefaultResourceBundle("com/opensymphony/webwork/webwork-messages");
// store a reference to ourself into the SessionContext so that we can
// generate a PageContext
// config.getPortletContext().setAttribute("webwork.servlet", this);
}
public void processAction(ActionRequest actionRequest,
ActionResponse actionResponse) throws PortletException, IOException
{
log.debug("Got to processAction!!");
try
{
serviceAction(actionRequest, actionResponse, getPortletName(),
getActionName(actionRequest),
getRequestMap(actionRequest),
getParameterMap(actionRequest),
getSessionMap(actionRequest), getPortletApplicationMap());
}
catch (Exception e)
{
if (e instanceof PortletException)
{
throw new PortletException(
"Error dispatching to WebWork Portlet",
(PortletException) e);
}
throw new PortletException("Error dispatching to WebWork Portlet");
}
}
public void render(RenderRequest request, RenderResponse response) throws PortletException, java.io.IOException
{
response.setTitle(getTitle(request));
log.debug("Rendering View Mode");
try
{
//response.setContentType("text/html");
//response.getWriter().println("doView APAPAPAPA <a href");
service(request, response);
}
catch (Exception e)
{
e.printStackTrace();
throw new PortletException("Error dispatching to WebWork Portlet");
}
}
protected void doDispatch(RenderRequest renderRequest, RenderResponse renderResponse) throws PortletException, IOException
{
}
public void service(PortletRequest request, PortletResponse response) throws PortletException
{
log.debug("Getting to serviceAction");
serviceAction(request, response, getPortletName(),
getActionName(request),
getRequestMap(request), getParameterMap(request),
getSessionMap(request), getPortletApplicationMap());
}
public void serviceAction(PortletRequest request, PortletResponse response,
String namespace, String actionName, Map requestMap,
Map parameterMap, Map sessionMap, Map applicationMap)
{
addSession(request);
log.debug("Getting to serviceAction with namespace:" + namespace + " actionName:" + actionName);
HashMap extraContext = createContextMap(requestMap, parameterMap, sessionMap, applicationMap, request, response, getPortletConfig());
if (namespace.length() > 0)
{
namespace = new StringBuffer("/").append(namespace).toString();
}
if(log.isDebugEnabled())
log.debug(sessionMap);
if(log.isDebugEnabled())
log.debug(parameterMap);
extraContext.put(PORTLET_DISPATCHER, this);
if(log.isDebugEnabled())
log.debug("Getting to beginning of serviceAction");
if(log.isDebugEnabled())
log.debug(new StringBuffer().append("Namespace: ").append(namespace).append("\nAction: ").append(actionName).append("\nPortlet Name: ").append(getPortletName()).toString());
try
{
if (request instanceof RenderRequest)
{
log.debug("Yes - it was a render request....");
if (request.getPortletSession(true).getAttribute(ACTION_CONTEXT) != null)
{
log.debug("Getting key for old action");
// String oldActionKey = request.getParameter("com.opensymphony.webwork.portlet.ActionContextKey");
ActionContext oldAction = (ActionContext) request.getPortletSession().getAttribute(ACTION_CONTEXT);
extraContext.put(ActionContext.VALUE_STACK, oldAction.getValueStack());
extraContext.put(ActionContext.PARAMETERS, oldAction.getParameters());
request.getPortletSession().removeAttribute(ACTION_CONTEXT);
log.debug("Should have removed the key");
}
}
String actionOverride = (String) request.getParameter("xwork.action");
if (actionOverride != null)
{
log.debug("Override action is " + actionOverride);
actionName = actionOverride;
}
ActionProxy proxy = ActionProxyFactory.getFactory().createActionProxy(namespace, actionName, extraContext);
request.setAttribute("webwork.valueStack", proxy.getInvocation().getStack());
proxy.execute();
//TODO: This code is a B.S. cheat by me. Need to figure out if this is even needed.
if (request instanceof ActionRequest)
{
request.getPortletSession().setAttribute(ACTION_CONTEXT, proxy.getInvocation().getInvocationContext());
}
request.removeAttribute("webwork.valueStack");
}
catch (ConfigurationException e)
{
log.error("Could not find action:" + e.getMessage());
//sendError(request, response, HttpServletResponse.SC_NOT_FOUND, e);
disposeSession(request);
}
catch (Exception e)
{
log.error("Could not execute action", e);
//sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
disposeSession(request);
}
catch (Throwable e)
{
log.error("Could not execute action", e);
//sendError(request, response, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
disposeSession(request);
}
}
/**
* Build the name of the action from the request. Checks the request parameter
* <code>action</action> for the action name
*
* @param request the HttpServletRequest object.
* @return the name or alias of the action to execute.
*/
protected String getActionName(ActionRequest request) {
String actionName = request.getParameter("action");
if(actionName == null) {
actionName = "default";
}
log.debug("actionName = " + actionName);
return actionName;
}
/**
* Build the name of the action from the request. Checks the request parameter
* <code>action</action> for the action name
*
* @param request the HttpServletRequest object.
* @return the name or alias of the action to execute.
*/
protected String getActionName(PortletRequest request) {
String actionName = request.getParameter("action");
log.debug("request actionName = " + actionName);
if(actionName == null) {
actionName = (String) getPortletConfig().getInitParameter(request.getPortletMode().toString());
}
log.debug("actionName = " + actionName);
return actionName;
}
protected String getModeActionName(PortletMode mode) throws PortletException
{
log.debug("PortletMode is: " + mode.toString());
// TODO: Move this exception throwing somewhere else. Nested too deep.
String actionName = (String) getPortletConfig().getInitParameter(mode.toString());
log.debug("actionName in getModeActionName:" + actionName);
if (actionName == null)
{
throw new PortletException("Can't find portlet init param for " + mode.toString() + " action");
}
return actionName;
}
protected Map getPortletApplicationMap()
{
return new PortletApplicationMap(getPortletContext());
}
protected Map getParameterMap(PortletRequest request)
{
return request.getParameterMap();
}
protected Map getRequestMap(PortletRequest request)
{
return new PortletRequestMap(request);
}
protected Map getSessionMap(PortletRequest request)
{
return new PortletSessionMap(request);
}
protected void sendError(PortletRequest request, PortletResponse response, int code, Exception e)
{
request.setAttribute("javax.servlet.error.exception", e);
// for compatibility
request.setAttribute("javax.servlet.jsp.jspException", e);
}
private Session session;
private Transaction transaction;
private static SessionFactory factory = null;
static
{
try
{
Configuration cfg = new Configuration();
cfg.configure();
cfg.setListeners("load", new LoadEventListener [] {new DefaultLoadEventListener(), new LoadEventListener() {
public void onLoad(LoadEvent event, LoadType loadType) throws HibernateException {
Object obj = event.getResult();
if (obj instanceof HibernateProxy) {
Enhancer.registerCallbacks(obj.getClass(),null);
}
}
}});
factory = cfg.buildSessionFactory();
}
catch (Exception e)
{
System.out.println("Could not connect to database:" + e.getMessage());
}
}
private void addSession(PortletRequest request)
{
log.debug("Initializing session:" + factory);
if(factory != null)
{
Session session = factory.openSession();
log.debug("Initializing session:" + session);
transaction = session.beginTransaction();
request.setAttribute("HIBERNATE_SESSION", session);
request.setAttribute("HIBERNATE_TRANSACTION", transaction);
}
else
{
request.setAttribute("DATABASE_CONFIGURATION_ERROR", "No database connection could be made");
}
}
public Session getSession(PortletRequest request) throws HibernateException
{
return (Session)request.getAttribute("HIBERNATE_SESSION");
}
public Transaction getTransaction(PortletRequest request) throws HibernateException
{
return (Transaction)request.getAttribute("HIBERNATE_TRANSACTION");
}
public void emptySession(PortletRequest request) throws HibernateException
{
request.removeAttribute("HIBERNATE_SESSION");
}
public void emptyTransaction(PortletRequest request) throws HibernateException
{
request.removeAttribute("HIBERNATE_TRANSACTION");
}
public void emptyValueStack(PortletRequest request) throws HibernateException
{
request.removeAttribute("webwork.valueStack");
}
boolean rollBackOnly = false;
public void disposeSession(PortletRequest request) throws HibernateException {
log.debug("disposing");
if (getSession(request)==null) return;
if (rollBackOnly)
{
try
{
log.debug("rolling back");
if (getTransaction(request)!=null) getTransaction(request).rollback();
}
catch (HibernateException e)
{
log.error("error during rollback", e);
throw e;
}
finally
{
try
{
getSession(request).close();
}
finally
{
emptySession(request);
emptyTransaction(request);
emptyValueStack(request);
}
}
}
else
{
try
{
log.debug("committing");
if (getTransaction(request)!=null)
{
getTransaction(request).commit();
}
}
catch (HibernateException e)
{
log.error("error during commit", e);
getTransaction(request).rollback();
throw e;
}
finally
{
try
{
getSession(request).close();
}
finally
{
emptySession(request);
emptyTransaction(request);
emptyValueStack(request);
}
}
}
}
protected PortletContext getPortletContext(PortletSession session)
{
return session.getPortletContext();
}
protected DefaultComponentManager createComponentManager()
{
return new DefaultComponentManager();
}
}