001: package com.icesoft.faces.webapp.http.servlet;
002:
003: import com.icesoft.faces.context.View;
004: import com.icesoft.faces.util.event.servlet.ContextEventRepeater;
005: import com.icesoft.faces.webapp.command.CommandQueue;
006: import com.icesoft.faces.webapp.command.SessionExpired;
007: import com.icesoft.faces.webapp.http.common.Configuration;
008: import com.icesoft.faces.webapp.http.common.Request;
009: import com.icesoft.faces.webapp.http.common.Server;
010: import com.icesoft.faces.webapp.http.common.standard.OKHandler;
011: import com.icesoft.faces.webapp.http.common.standard.PathDispatcherServer;
012: import com.icesoft.faces.webapp.http.core.AsyncServerDetector;
013: import com.icesoft.faces.webapp.http.core.DisposeViews;
014: import com.icesoft.faces.webapp.http.core.IDVerifier;
015: import com.icesoft.faces.webapp.http.core.MultiViewServer;
016: import com.icesoft.faces.webapp.http.core.ReceivePing;
017: import com.icesoft.faces.webapp.http.core.ReceiveSendUpdates;
018: import com.icesoft.faces.webapp.http.core.SendUpdates;
019: import com.icesoft.faces.webapp.http.core.SingleViewServer;
020: import com.icesoft.faces.webapp.http.core.UploadServer;
021: import com.icesoft.faces.webapp.http.core.ViewBoundServer;
022: import com.icesoft.faces.webapp.http.core.ViewQueue;
023: import com.icesoft.util.IdGenerator;
024: import org.apache.commons.logging.Log;
025: import org.apache.commons.logging.LogFactory;
026:
027: import javax.servlet.http.HttpServletRequest;
028: import javax.servlet.http.HttpServletResponse;
029: import javax.servlet.http.HttpSession;
030: import java.util.Collection;
031: import java.util.HashMap;
032: import java.util.HashSet;
033: import java.util.Iterator;
034: import java.util.Map;
035:
036: public class MainSessionBoundServlet implements PseudoServlet {
037: private static final Log Log = LogFactory
038: .getLog(MainSessionBoundServlet.class);
039: private static final SessionExpired SessionExpired = new SessionExpired();
040: private static final Server NOOPServer = new Server() {
041: public void service(Request request) throws Exception {
042: request.respondWith(OKHandler.HANDLER);
043: }
044:
045: public void shutdown() {
046: }
047: };
048: private Runnable drainUpdatedViews = new Runnable() {
049: public void run() {
050: allUpdatedViews.removeAll(synchronouslyUpdatedViews);
051: if (!allUpdatedViews.isEmpty()) {
052: Log.warn(allUpdatedViews
053: + " views have accumulated updates");
054: }
055: allUpdatedViews.clear();
056: }
057: };
058: private Map views = new HashMap();
059: private ViewQueue allUpdatedViews = new ViewQueue();
060: private Collection synchronouslyUpdatedViews = new HashSet();
061: private String sessionID;
062: private PseudoServlet servlet;
063: private HttpSession session;
064:
065: public MainSessionBoundServlet(HttpSession session,
066: SessionDispatcher.Listener.Monitor sessionMonitor,
067: IdGenerator idGenerator, Configuration configuration) {
068: this .session = session;
069: sessionID = idGenerator.newIdentifier();
070: ContextEventRepeater.iceFacesIdRetrieved(session, sessionID);
071:
072: final Server viewServlet;
073: final Server disposeViews;
074: if (configuration.getAttributeAsBoolean("concurrentDOMViews",
075: false)) {
076: viewServlet = new MultiViewServer(session, sessionID,
077: sessionMonitor, views, allUpdatedViews,
078: configuration);
079: disposeViews = new IDVerifier(sessionID, new DisposeViews(
080: views));
081: } else {
082: viewServlet = new SingleViewServer(session, sessionID,
083: sessionMonitor, views, allUpdatedViews,
084: configuration);
085: disposeViews = NOOPServer;
086: }
087:
088: final Server sendUpdatedViews;
089: final Server sendUpdates;
090: final Server receivePing;
091: if (configuration.getAttributeAsBoolean("synchronousUpdate",
092: false)) {
093: //drain the updated views queue if in 'synchronous mode'
094: allUpdatedViews.onPut(drainUpdatedViews);
095: sendUpdatedViews = NOOPServer;
096: sendUpdates = NOOPServer;
097: receivePing = NOOPServer;
098: } else {
099: //setup blocking connection server
100: sendUpdatedViews = new IDVerifier(sessionID,
101: new AsyncServerDetector(sessionID,
102: synchronouslyUpdatedViews, allUpdatedViews,
103: session.getServletContext(), configuration));
104: sendUpdates = new IDVerifier(sessionID, new SendUpdates(
105: views));
106: receivePing = new IDVerifier(sessionID, new ReceivePing(
107: views));
108: }
109:
110: Server upload = new UploadServer(views, configuration);
111: Server receiveSendUpdates = new ViewBoundServer(new IDVerifier(
112: sessionID, new ReceiveSendUpdates(views,
113: synchronouslyUpdatedViews)), sessionMonitor,
114: views);
115:
116: PathDispatcherServer dispatcher = new PathDispatcherServer();
117: dispatcher.dispatchOn(".*block\\/send\\-receive\\-updates$",
118: receiveSendUpdates);
119: dispatcher.dispatchOn(".*block\\/receive\\-updated\\-views$",
120: sendUpdatedViews);
121: dispatcher.dispatchOn(".*block\\/receive\\-updates$",
122: sendUpdates);
123: dispatcher.dispatchOn(".*block\\/ping$", receivePing);
124: dispatcher.dispatchOn(".*block\\/dispose\\-views$",
125: disposeViews);
126: dispatcher.dispatchOn(".*uploadHtml", upload);
127: dispatcher.dispatchOn(".*", viewServlet);
128: servlet = new EnvironmentAdaptingServlet(dispatcher,
129: configuration);
130: }
131:
132: public void service(HttpServletRequest request,
133: HttpServletResponse response) throws Exception {
134: servlet.service(request, response);
135: }
136:
137: public void shutdown() {
138: Iterator i = views.values().iterator();
139: while (i.hasNext()) {
140: CommandQueue commandQueue = (CommandQueue) i.next();
141: commandQueue.put(SessionExpired);
142: }
143: ContextEventRepeater.iceFacesIdDisposed(session, sessionID);
144: try {
145: //wait for the for the bridge to receive the 'session-expire' command
146: Thread.sleep(1000);
147: } catch (InterruptedException e) {
148: //do nothing
149: } finally {
150: servlet.shutdown();
151: }
152:
153: Iterator viewIterator = views.values().iterator();
154: while (viewIterator.hasNext()) {
155: View view = (View) viewIterator.next();
156: view.dispose();
157: }
158: }
159:
160: //Exposing queues for Tomcat 6 Ajax Push
161: public ViewQueue getAllUpdatedViews() {
162: return allUpdatedViews;
163: }
164:
165: public Collection getSynchronouslyUpdatedViews() {
166: return synchronouslyUpdatedViews;
167: }
168: }
|