/*
* This file is part of the WfMOpen project.
* Copyright (C) 2001-2005 Danet GmbH (www.danet.de), BU BTS.
* All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: MyFacesAjaxServlet.java 2921 2009-02-14 20:41:30Z mlipp $
*
* $Log$
* Revision 1.1.2.6 2006/11/28 13:08:42 drmlipp
* Started Ajax response handling.
*
* Revision 1.1.2.5 2006/11/27 14:28:33 drmlipp
* Continuing.
*
* Revision 1.1.2.4 2006/11/26 21:16:15 mlipp
* Getting Ajax call back to component.
*
* Revision 1.1.2.3 2006/11/25 22:45:56 mlipp
* Got request through to JSF.
*
* Revision 1.1.2.2 2006/11/24 16:15:31 drmlipp
* Continuing Ajax support.
*
* Revision 1.1.2.1 2006/11/23 23:00:53 mlipp
* Started AJAX handling.
*
* Revision 1.2 2006/09/29 12:32:11 drmlipp
* Consistently using WfMOpen as projct name now.
*
* Revision 1.1 2006/09/11 15:29:28 drmlipp
* Improved portlet support.
*
*/
package de.danet.an.util.jsf;
import java.io.IOException;
import java.util.Map;
import javax.faces.FactoryFinder;
import javax.faces.application.ViewHandler;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.context.FacesContextFactory;
import javax.faces.lifecycle.Lifecycle;
import javax.faces.lifecycle.LifecycleFactory;
import javax.portlet.RenderResponse;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.myfaces.context.servlet.ServletFacesContextImpl;
import org.apache.myfaces.portlet.MyFacesGenericPortlet;
import org.apache.myfaces.shared_tomahawk.util._ComponentUtils;
import de.danet.an.util.logging.RequestLog;
import de.danet.an.util.logging.RequestScope;
/**
* This class provides a servlet that provides MyFaces resources.
*
* @author Michael Lipp
*
*/
public class MyFacesAjaxServlet extends HttpServlet {
private static final org.apache.commons.logging.Log logger
= org.apache.commons.logging.LogFactory.getLog(MyFacesAjaxServlet.class);
public static final String RENDER_NAMESPACE
= MyFacesAdaptedPortlet.class.getName() + ".RENDER_NAMESPACE";
public static final String AJAX_CALL_TO
= MyFacesAdaptedPortlet.class.getName() + ".AJAX_CALL_TO";
protected LifecycleFactory lifecycleFactory;
protected FacesContextFactory facesContextFactory;
/* (non-Javadoc)
* @see javax.servlet.GenericServlet#init()
*/
public void init() throws ServletException {
super.init();
lifecycleFactory = (LifecycleFactory)
FactoryFinder.getFactory(FactoryFinder.LIFECYCLE_FACTORY);
facesContextFactory = (FacesContextFactory) FactoryFinder
.getFactory(FactoryFinder.FACES_CONTEXT_FACTORY);
}
/* (non-Javadoc)
* @see javax.servlet.http.HttpServlet#doGet
*/
protected void doPost
(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
RequestScope scope = RequestLog.enterScope
(this, "doPost", new Object[] { request, response });
try {
if (logger.isDebugEnabled()) {
logger.debug("Ajax request: " + request.getRequestURL());
}
if (request.getSession(false) == null) {
response.sendError(HttpServletResponse.SC_GONE);
return;
}
// make external context
AjaxExternalContext externalContext
= AjaxExternalContext.makeContext(request, response);
// use session map to access portlet session
Map sessionMap = externalContext.getSessionMap();
// restore faces context
String lifecycleId = (String)
sessionMap.get(MyFacesAdaptedPortlet.LIFECYCLE_ID);
if (lifecycleId == null) {
response.sendError(HttpServletResponse.SC_NOT_FOUND);
return;
}
Lifecycle lifecycle = lifecycleFactory.getLifecycle(lifecycleId);
ServletFacesContextImpl facesContext = (ServletFacesContextImpl)
facesContextFactory.getFacesContext
(getServletContext(), request, response, lifecycle);
facesContext.setExternalContext(externalContext);
lifecycle.execute(facesContext);
facesContext.getApplication()
.getStateManager().saveSerializedView(facesContext);
} finally {
scope.leave();
}
}
protected void doGet
(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
doPost (request, response);
}
public static String getAjaxActionUrl
(FacesContext context, UIComponent component) {
// We have to bypass the portal because an Ajax request does not
// fit in the action/render pattern. Therfore we provide access to
// this servlet as a resource
ViewHandler viewHandler = context.getApplication().getViewHandler();
String path = viewHandler.getResourceURL(context, "/ajax");
StringBuffer res = new StringBuffer(path);
if (res.indexOf("?") < 0) {
res.append("?");
} else {
res.append("&");
}
// MyFaces retrieves the view id of request from a special request
// parameter, add it.
String viewId = context.getViewRoot().getViewId();
res.append(MyFacesGenericPortlet.VIEW_ID);
res.append("=");
res.append(viewId);
// Add a hint that allows us to identify the portlets session data.
res.append("&");
res.append(MyFacesAjaxServlet.RENDER_NAMESPACE);
res.append("=");
res.append(((RenderResponse)context.getExternalContext().getResponse())
.getNamespace());
// Special request parameter required by MyFaces to pass the request
// to the form's children.
res.append("&");
String hiddenFieldName = _ComponentUtils
.findNestingForm(component, context).getForm()
.getClientId(context) + "_SUBMIT";
res.append(hiddenFieldName);
res.append("=1");
// Finally, allow component to find out that it's being addressed.
res.append("&");
res.append(AJAX_CALL_TO);
res.append("=");
res.append(component.getClientId(context));
return res.toString();
}
}