001: package com.icesoft.faces.context;
002:
003: import com.icesoft.faces.env.PortletEnvironmentRenderRequest;
004: import com.icesoft.faces.env.ServletEnvironmentRequest;
005: import com.icesoft.faces.webapp.command.Command;
006: import com.icesoft.faces.webapp.command.CommandQueue;
007: import com.icesoft.faces.webapp.command.NOOP;
008: import com.icesoft.faces.webapp.http.common.Configuration;
009: import com.icesoft.faces.webapp.http.common.Request;
010: import com.icesoft.faces.webapp.http.core.ViewQueue;
011: import com.icesoft.faces.webapp.http.portlet.PortletExternalContext;
012: import com.icesoft.faces.webapp.http.servlet.ServletExternalContext;
013: import com.icesoft.faces.webapp.http.servlet.SessionDispatcher;
014: import com.icesoft.faces.webapp.xmlhttp.PersistentFacesState;
015: import com.icesoft.util.SeamUtilities;
016: import edu.emory.mathcs.backport.java.util.concurrent.locks.Lock;
017: import edu.emory.mathcs.backport.java.util.concurrent.locks.ReentrantLock;
018: import org.apache.commons.logging.Log;
019: import org.apache.commons.logging.LogFactory;
020:
021: import javax.servlet.http.HttpServletRequest;
022: import javax.servlet.http.HttpServletResponse;
023: import java.util.ArrayList;
024: import java.util.Collection;
025: import java.util.Collections;
026: import java.util.Iterator;
027: import java.util.Map;
028:
029: public class View implements CommandQueue {
030: private static final Log Log = LogFactory.getLog(View.class);
031: private static final NOOP NOOP = new NOOP();
032: private Lock lock = new ReentrantLock();
033: private BridgeExternalContext externalContext;
034: private BridgeFacesContext facesContext;
035: private PersistentFacesState persistentFacesState;
036: private Map bundles = Collections.EMPTY_MAP;
037: private String requestURI;
038: private Command currentCommand = NOOP;
039: private String viewIdentifier;
040: private ArrayList onPutListeners = new ArrayList();
041: private ArrayList onTakeListeners = new ArrayList();
042: private Collection viewListeners = new ArrayList();
043: private String sessionID;
044: private Configuration configuration;
045: private SessionDispatcher.Listener.Monitor sessionMonitor;
046:
047: public View(final String viewIdentifier, String sessionID,
048: Request request, final ViewQueue allServedViews,
049: final Configuration configuration,
050: final SessionDispatcher.Listener.Monitor sessionMonitor)
051: throws Exception {
052: this .sessionID = sessionID;
053: this .configuration = configuration;
054: this .viewIdentifier = viewIdentifier;
055: this .sessionMonitor = sessionMonitor;
056: request.detectEnvironment(new Request.Environment() {
057: public void servlet(Object request, Object response) {
058: ServletEnvironmentRequest wrappedRequest = new ServletEnvironmentRequest(
059: request);
060: requestURI = wrappedRequest.getRequestURI();
061: externalContext = new ServletExternalContext(
062: viewIdentifier, wrappedRequest, response,
063: View.this , configuration, sessionMonitor);
064: }
065:
066: public void portlet(Object request, Object response,
067: Object portletConfig) {
068: PortletEnvironmentRenderRequest wrappedRequest = new PortletEnvironmentRenderRequest(
069: request);
070: externalContext = new PortletExternalContext(
071: viewIdentifier, wrappedRequest, response,
072: View.this , configuration, sessionMonitor,
073: portletConfig);
074: }
075: });
076: this .facesContext = new BridgeFacesContext(externalContext,
077: viewIdentifier, sessionID, this , configuration);
078: this .persistentFacesState = new PersistentFacesState(
079: facesContext, viewListeners, configuration);
080: this .onPut(new Runnable() {
081: public void run() {
082: try {
083: allServedViews.put(viewIdentifier);
084: } catch (InterruptedException e) {
085: Log.warn("Failed to queue updated view", e);
086: }
087: }
088: });
089: this .notifyViewCreation();
090: }
091:
092: public void updateOnXMLHttpRequest(Request request)
093: throws Exception {
094: request.detectEnvironment(new Request.Environment() {
095: public void servlet(Object request, Object response) {
096: externalContext.update((HttpServletRequest) request,
097: (HttpServletResponse) response);
098: }
099:
100: public void portlet(Object request, Object response,
101: Object config) {
102: //this call cannot arrive from a Portlet
103: }
104: });
105: makeCurrent();
106: }
107:
108: public void updateOnRequest(Request request) throws Exception {
109: request.detectEnvironment(new Request.Environment() {
110: public void servlet(Object request, Object response) {
111: HttpServletRequest wrappedRequest = new ServletEnvironmentRequest(
112: request);
113: if (differentURI(wrappedRequest)) {
114: //page redirect
115: requestURI = wrappedRequest.getRequestURI();
116: externalContext = new ServletExternalContext(
117: viewIdentifier, wrappedRequest, response,
118: View.this , configuration, sessionMonitor);
119: facesContext = new BridgeFacesContext(
120: externalContext, viewIdentifier, sessionID,
121: View.this , configuration);
122: //reuse PersistentFacesState instance when page redirects occur
123: persistentFacesState.setFacesContext(facesContext);
124: } else {
125: //page reload
126: externalContext.updateOnReload(wrappedRequest,
127: response);
128: }
129: }
130:
131: public void portlet(Object request, Object response,
132: Object config) {
133: //page reload
134: PortletEnvironmentRenderRequest wrappedRequest = new PortletEnvironmentRenderRequest(
135: request);
136: externalContext
137: .updateOnReload(wrappedRequest, response);
138: }
139: });
140: makeCurrent();
141: }
142:
143: public void switchToNormalMode() {
144: facesContext.switchToNormalMode();
145: externalContext.switchToNormalMode();
146: }
147:
148: public void switchToPushMode() {
149: //collect bundles put by Tag components when the page is parsed
150: bundles = externalContext.collectBundles();
151: facesContext.switchToPushMode();
152: externalContext.switchToPushMode();
153: }
154:
155: /**
156: * Check to see if the URI is different in any material (or Seam) way.
157: *
158: * @param request ServletRequest
159: * @return true if the URI is considered different
160: */
161: public boolean differentURI(HttpServletRequest request) {
162: // As a temporary fix, all GET requests are non-faces requests, and thus,
163: // are considered different to force a new ViewRoot to be constructed.
164: return (SeamUtilities.isSeamEnvironment())
165: || !request.getRequestURI().equals(requestURI);
166: }
167:
168: public void put(Command command) {
169: lock.lock();
170: currentCommand = currentCommand.coalesceWith(command);
171: lock.unlock();
172: broadcastTo(onPutListeners);
173: }
174:
175: public Command take() {
176: lock.lock();
177: Command command = currentCommand;
178: currentCommand = NOOP;
179: lock.unlock();
180: broadcastTo(onTakeListeners);
181: return command;
182: }
183:
184: public void onPut(Runnable listener) {
185: onPutListeners.add(listener);
186: }
187:
188: public void onTake(Runnable listener) {
189: onTakeListeners.add(listener);
190: }
191:
192: private void broadcastTo(Collection listeners) {
193: Iterator i = listeners.iterator();
194: while (i.hasNext()) {
195: Runnable listener = (Runnable) i.next();
196: try {
197: listener.run();
198: } catch (Exception e) {
199: Log.error("Failed to notify listener: " + listener, e);
200: }
201: }
202: }
203:
204: public void release() {
205: facesContext.release();
206: persistentFacesState.release();
207: externalContext.resetRequestMap();
208: }
209:
210: public BridgeFacesContext getFacesContext() {
211: return facesContext;
212: }
213:
214: public void dispose() {
215: this .persistentFacesState.setCurrentInstance();
216: this .facesContext.setCurrentInstance();
217: this .notifyViewDisposal();
218: this .release();
219: this .facesContext.dispose();
220: this .externalContext.dispose();
221: }
222:
223: public void makeCurrent() {
224: externalContext.injectBundles(bundles);
225: persistentFacesState.setCurrentInstance();
226: facesContext.setCurrentInstance();
227: facesContext.applyBrowserDOMChanges();
228: }
229:
230: private void notifyViewCreation() {
231: Iterator i = viewListeners.iterator();
232: while (i.hasNext()) {
233: try {
234: ViewListener listener = (ViewListener) i.next();
235: listener.viewCreated();
236: } catch (Throwable t) {
237: Log.warn("Failed to invoke view listener", t);
238: }
239: }
240: }
241:
242: private void notifyViewDisposal() {
243: Iterator i = viewListeners.iterator();
244: while (i.hasNext()) {
245: try {
246: ViewListener listener = (ViewListener) i.next();
247: listener.viewDisposed();
248: } catch (Throwable t) {
249: Log.warn("Failed to invoke view listener", t);
250: }
251: }
252: }
253: }
|