Index: core/src/com/icesoft/faces/context/View.java =================================================================== --- core/src/com/icesoft/faces/context/View.java (revision 17555) +++ core/src/com/icesoft/faces/context/View.java (working copy) @@ -15,6 +15,7 @@ import com.icesoft.faces.webapp.http.servlet.ServletExternalContext; import com.icesoft.faces.webapp.http.servlet.SessionDispatcher; import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState; +import com.icesoft.faces.util.event.servlet.ContextEventRepeater; import com.icesoft.util.SeamUtilities; import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock; import org.apache.commons.logging.Log; @@ -22,15 +23,19 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; import javax.faces.lifecycle.LifecycleFactory; import javax.faces.lifecycle.Lifecycle; import javax.faces.FactoryFinder; import javax.faces.context.FacesContext; +import javax.portlet.PortletConfig; +import javax.portlet.RenderRequest; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Map; +import java.io.ObjectInputStream; public class View implements CommandQueue { private static final Log Log = LogFactory.getLog(View.class); @@ -67,26 +72,21 @@ private ResourceDispatcher resourceDispatcher; private Runnable dispose; private Lifecycle lifecycle; + private HttpSession session; - public View(final String viewIdentifier, String sessionID, Request request, final ViewQueue allServedViews, final Configuration configuration, final SessionDispatcher.Monitor sessionMonitor, ResourceDispatcher resourceDispatcher, Lifecycle lifecycle) throws Exception { + public View(final String viewIdentifier, String sessionID, final HttpSession session, final ViewQueue allServedViews, final Configuration configuration, final SessionDispatcher.Monitor sessionMonitor, ResourceDispatcher resourceDispatcher, Lifecycle lifecycle) throws Exception { this.sessionID = sessionID; + this.session = session; this.configuration = configuration; this.viewIdentifier = viewIdentifier; this.sessionMonitor = sessionMonitor; this.resourceDispatcher = resourceDispatcher; this.lifecycle = lifecycle; + ContextEventRepeater.viewNumberRetrieved(session, sessionID, Integer.parseInt(viewIdentifier)); + //fail fast if environment cannot be detected this.externalContext = new UnknownExternalContext(this, configuration); - request.detectEnvironment(new Request.Environment() { - public void servlet(Object request, Object response) { - externalContext = new ServletExternalContext(viewIdentifier, request, response, View.this, configuration, sessionMonitor); - } - - public void portlet(Object request, Object response, Object portletConfig) { - externalContext = new PortletExternalContext(viewIdentifier, request, response, View.this, configuration, sessionMonitor, portletConfig); - } - }); this.facesContext = new BridgeFacesContext(externalContext, viewIdentifier, sessionID, this, configuration, resourceDispatcher); this.persistentFacesState = new PersistentFacesState(facesContext, lifecycleLock, viewListeners, configuration); this.onPut(new Runnable() { @@ -143,20 +143,23 @@ if (differentURI((HttpServletRequest) request)) { //page redirect externalContext.dispose(); - externalContext = new ServletExternalContext(viewIdentifier, request, response, View.this, configuration, sessionMonitor); + externalContext = new ServletExternalContext(viewIdentifier, session, View.this, configuration, sessionMonitor); facesContext.dispose(); facesContext = new BridgeFacesContext(externalContext, viewIdentifier, sessionID, View.this, configuration, resourceDispatcher); //reuse PersistentFacesState instance when page redirects occur persistentFacesState.setFacesContext(facesContext); - } else { - //page reload + } externalContext.updateOnPageLoad(request, response); } - } public void portlet(Object request, Object response, Object config) { //page reload - externalContext.updateOnPageLoad(request, response); + externalContext.dispose(); + externalContext = new PortletExternalContext(viewIdentifier, ((RenderRequest) request).getPortletSession(), View.this, configuration, sessionMonitor, config); + facesContext.dispose(); + facesContext = new BridgeFacesContext(externalContext, viewIdentifier, sessionID, View.this, configuration, resourceDispatcher); + //reuse PersistentFacesState instance when page redirects occur + persistentFacesState.setFacesContext(facesContext); } }); makeCurrent(); @@ -272,6 +275,7 @@ } public void servePage(Request request) throws Exception { + updateOnPageRequest(request); request.respondWith(responseHandler); } @@ -283,4 +287,8 @@ } }; } + + public static View restore(ObjectInputStream in) { + return null; //To change body of created methods use File | Settings | File Templates. + } } \ No newline at end of file Index: core/src/com/icesoft/faces/webapp/http/servlet/MainSessionBoundServlet.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/servlet/MainSessionBoundServlet.java (revision 17555) +++ core/src/com/icesoft/faces/webapp/http/servlet/MainSessionBoundServlet.java (working copy) @@ -25,7 +25,6 @@ import com.icesoft.faces.webapp.http.core.ViewQueue; import com.icesoft.net.messaging.MessageHandler; import com.icesoft.net.messaging.MessageServiceClient; -import com.icesoft.util.IdGenerator; import com.icesoft.util.MonitorRunner; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -37,6 +36,11 @@ import java.util.HashSet; import java.util.Iterator; import java.util.Map; +import java.util.ArrayList; +import java.util.List; +import java.io.ObjectOutputStream; +import java.io.ObjectInputStream; +import java.io.IOException; //todo: rename to MainSessionBoundServer and move in com.icesoft.faces.webapp.http.core public class MainSessionBoundServlet implements Server { @@ -65,8 +69,8 @@ private final String sessionID; private Runnable shutdown; - public MainSessionBoundServlet(final HttpSession session, final SessionDispatcher.Monitor sessionMonitor, IdGenerator idGenerator, MimeTypeMatcher mimeTypeMatcher, MonitorRunner monitorRunner, Configuration configuration, final MessageServiceClient messageService) { - sessionID = idGenerator.newIdentifier(); + public MainSessionBoundServlet(final HttpSession session, final SessionDispatcher.Monitor sessionMonitor, final String sessionID, MimeTypeMatcher mimeTypeMatcher, MonitorRunner monitorRunner, Configuration configuration, final MessageServiceClient messageService) { + this.sessionID = sessionID; ContextEventRepeater.iceFacesIdRetrieved(session, sessionID); final ResourceDispatcher resourceDispatcher = new ResourceDispatcher(ResourcePrefix, mimeTypeMatcher, sessionMonitor, configuration); final Server viewServlet; @@ -180,4 +184,25 @@ public String getSessionID() { return sessionID; } + + public void save(ObjectOutputStream out) throws IOException { + out.writeUTF(sessionID); + out.writeObject(new ArrayList(allUpdatedViews)); + out.writeObject(new ArrayList(views.keySet())); + } + + public void restore(ObjectInputStream in) throws IOException, ClassNotFoundException { + allUpdatedViews.addAll((List) in.readObject()); + Iterator i = ((List) in.readObject()).iterator(); + while (i.hasNext()) { + String viewIdentifier = (String) i.next(); + } + } + + public static MainSessionBoundServlet restore(ObjectInputStream in, final HttpSession session, final SessionDispatcher.Monitor sessionMonitor, MimeTypeMatcher mimeTypeMatcher, MonitorRunner monitorRunner, Configuration configuration, final MessageServiceClient messageService) throws IOException, ClassNotFoundException { + String sessionID = in.readUTF(); + MainSessionBoundServlet instance = new MainSessionBoundServlet(session, sessionMonitor, sessionID, mimeTypeMatcher, monitorRunner, configuration, messageService); + instance.restore(in); + return instance; + } } Index: core/src/com/icesoft/faces/webapp/http/servlet/MainServlet.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/servlet/MainServlet.java (revision 17555) +++ core/src/com/icesoft/faces/webapp/http/servlet/MainServlet.java (working copy) @@ -69,7 +69,7 @@ PseudoServlet resourceServer = new BasicAdaptingServlet(new ResourceServer(configuration, mimeTypeMatcher, localFileLocator)); PseudoServlet sessionDispatcher = new SessionDispatcher(configuration, context) { protected Server newServer(HttpSession session, Monitor sessionMonitor) { - return new MainSessionBoundServlet(session, sessionMonitor, idGenerator, mimeTypeMatcher, monitorRunner, configuration, messageServiceClient); + return new MainSessionBoundServlet(session, sessionMonitor, idGenerator.newIdentifier(), mimeTypeMatcher, monitorRunner, configuration, messageServiceClient); } }; if (SeamUtilities.isSpringEnvironment()) { Index: core/src/com/icesoft/faces/webapp/http/servlet/ServletExternalContext.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/servlet/ServletExternalContext.java (revision 17555) +++ core/src/com/icesoft/faces/webapp/http/servlet/ServletExternalContext.java (working copy) @@ -42,17 +42,14 @@ private Dispatcher dispatcher; private List locales; - public ServletExternalContext(String viewIdentifier, final Object req, Object response, CommandQueue commandQueue, Configuration configuration, final SessionDispatcher.Monitor sessionMonitor) { + public ServletExternalContext(String viewIdentifier, HttpSession httpSession, CommandQueue commandQueue, Configuration configuration, final SessionDispatcher.Monitor sessionMonitor) { super(viewIdentifier, commandQueue, configuration); - HttpServletRequest request = (HttpServletRequest) req; - session = new InterceptingServletSession(request.getSession(), sessionMonitor); + session = new InterceptingServletSession(httpSession, sessionMonitor); context = session.getServletContext(); initParameterMap = new ServletContextInitParameterMap(context); applicationMap = new ServletContextAttributeMap(context); sessionMap = new ServletSessionAttributeMap(session); requestMap = Collections.EMPTY_MAP; - - updateOnPageLoad(request, response); insertNewViewrootToken(); // #ICE-1722 default to normal mode before the first request switchToNormalMode(); Index: core/src/com/icesoft/faces/webapp/http/core/SingleViewServer.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/core/SingleViewServer.java (revision 17555) +++ core/src/com/icesoft/faces/webapp/http/core/SingleViewServer.java (working copy) @@ -41,11 +41,8 @@ //create single view or re-create view if the request is the result of a redirect View view = (View) views.get(viewNumber); if (view == null) { - view = new View(viewNumber, sessionID, request, allUpdatedViews, configuration, sessionMonitor, resourceDispatcher, lifecycle); + view = new View(viewNumber, sessionID, session, allUpdatedViews, configuration, sessionMonitor, resourceDispatcher, lifecycle); views.put(viewNumber, view); - ContextEventRepeater.viewNumberRetrieved(session, sessionID, Integer.parseInt(viewNumber)); - } else { - view.updateOnPageRequest(request); } sessionMonitor.touchSession(); Index: core/src/com/icesoft/faces/webapp/http/core/MultiViewServer.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/core/MultiViewServer.java (revision 17555) +++ core/src/com/icesoft/faces/webapp/http/core/MultiViewServer.java (working copy) @@ -45,18 +45,11 @@ synchronized (views) { view = (View) views.get(redirectViewNumber); if (view == null) { - view = new View(redirectViewNumber, sessionID, request, asynchronouslyUpdatedViews, configuration, sessionMonitor, resourceDispatcher, lifecycle); - views.put(redirectViewNumber, view); - ContextEventRepeater.viewNumberRetrieved(session, sessionID, Integer.parseInt(redirectViewNumber)); - } else { - view.updateOnPageRequest(request); + view = newView(redirectViewNumber); } } } else { - String viewNumber = String.valueOf(++viewCount); - view = new View(viewNumber, sessionID, request, asynchronouslyUpdatedViews, configuration, sessionMonitor, resourceDispatcher, lifecycle); - views.put(viewNumber, view); - ContextEventRepeater.viewNumberRetrieved(session, sessionID, Integer.parseInt(viewNumber)); + view = newView(String.valueOf(++viewCount)); } sessionMonitor.touchSession(); view.servePage(request); @@ -65,4 +58,10 @@ public void shutdown() { } + + private View newView(String viewNumber) throws Exception { + View view = new View(viewNumber, sessionID, session, asynchronouslyUpdatedViews, configuration, sessionMonitor, resourceDispatcher, lifecycle); + views.put(viewNumber, view); + return view; + } } Index: core/src/com/icesoft/faces/webapp/http/portlet/PortletExternalContext.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/portlet/PortletExternalContext.java (revision 17555) +++ core/src/com/icesoft/faces/webapp/http/portlet/PortletExternalContext.java (working copy) @@ -74,14 +74,12 @@ public static final String INACTIVE_INCREMENT = "inactiveIncrement"; private boolean adjustPortletSessionInactiveInterval = true; - public PortletExternalContext(String viewIdentifier, final Object request, Object response, CommandQueue commandQueue, Configuration configuration, final SessionDispatcher.Monitor monitor, Object portletConfig) { + public PortletExternalContext(String viewIdentifier, PortletSession portletSession, CommandQueue commandQueue, Configuration configuration, final SessionDispatcher.Monitor monitor, Object portletConfig) { super(viewIdentifier, commandQueue, configuration); - final RenderRequest renderRequest = (RenderRequest) request; - final RenderResponse renderResponse = (RenderResponse) response; this.configuration = configuration; config = (PortletConfig) portletConfig; - session = new InterceptingPortletSession(renderRequest.getPortletSession(), monitor); + session = new InterceptingPortletSession(portletSession, monitor); context = session.getPortletContext(); initParameterMap = new PortletContextInitParameterMap(context); applicationMap = new PortletContextAttributeMap(context); @@ -92,7 +90,6 @@ adjustPortletSessionInactiveInterval = configuration.getAttributeAsBoolean("portlet.adjustSessionInactiveInterval", configuration.getAttributeAsBoolean("adjustPortletSessionInactiveInterval", true)); - updateOnPageLoad(renderRequest, renderResponse); insertNewViewrootToken(); switchToNormalMode(); } Index: core/src/com/icesoft/faces/webapp/http/portlet/MainPortlet.java =================================================================== --- core/src/com/icesoft/faces/webapp/http/portlet/MainPortlet.java (revision 17555) +++ core/src/com/icesoft/faces/webapp/http/portlet/MainPortlet.java (working copy) @@ -112,6 +112,7 @@ PortletArtifactWrapper wrapper = new PortletArtifactWrapper(portletConfig, renderRequest, renderResponse); addAttribute(renderRequest, PortletArtifactWrapper.PORTLET_ARTIFACT_KEY, wrapper); + renderRequest.getPortletSession().setAttribute("portlet", portletConfig); // Jack: This is a temporary fix for JBoss Portal. We should come up // with a better fix in our framework that makes sure the