001: package com.icesoft.faces.webapp.http.servlet;
002:
003: import com.icesoft.faces.context.AbstractAttributeMap;
004: import com.icesoft.faces.context.AbstractCopyingAttributeMap;
005: import com.icesoft.faces.context.BridgeExternalContext;
006: import com.icesoft.faces.util.EnumerationIterator;
007: import com.icesoft.faces.webapp.command.CommandQueue;
008: import com.icesoft.faces.webapp.http.common.Configuration;
009:
010: import javax.faces.FacesException;
011: import javax.servlet.ServletContext;
012: import javax.servlet.ServletException;
013: import javax.servlet.http.Cookie;
014: import javax.servlet.http.HttpServletRequest;
015: import javax.servlet.http.HttpServletResponse;
016: import javax.servlet.http.HttpSession;
017: import java.io.IOException;
018: import java.io.InputStream;
019: import java.io.OutputStreamWriter;
020: import java.io.Writer;
021: import java.net.MalformedURLException;
022: import java.net.URL;
023: import java.security.Principal;
024: import java.util.Collections;
025: import java.util.Enumeration;
026: import java.util.HashMap;
027: import java.util.Iterator;
028: import java.util.Locale;
029: import java.util.Map;
030: import java.util.Set;
031:
032: public class ServletExternalContext extends BridgeExternalContext {
033: private ServletContext context;
034: private HttpServletRequest request;
035: private HttpServletResponse response;
036: private HttpSession session;
037:
038: public ServletExternalContext(String viewIdentifier,
039: final Object request, Object response,
040: CommandQueue commandQueue, Configuration configuration,
041: final SessionDispatcher.Listener.Monitor sessionMonitor) {
042: super (viewIdentifier, commandQueue, configuration);
043: this .request = (HttpServletRequest) request;
044: this .response = (HttpServletResponse) response;
045: this .session = new InterceptingHttpSession(this .request
046: .getSession(), sessionMonitor);
047: this .context = this .session.getServletContext();
048: this .initParameterMap = new AbstractAttributeMap() {
049: protected Object getAttribute(String key) {
050: return context.getInitParameter(key);
051: }
052:
053: protected void setAttribute(String key, Object value) {
054: throw new IllegalAccessError("Read only map.");
055: }
056:
057: protected void removeAttribute(String key) {
058: throw new IllegalAccessError("Read only map.");
059: }
060:
061: protected Enumeration getAttributeNames() {
062: return context.getInitParameterNames();
063: }
064: };
065: this .applicationMap = new AbstractAttributeMap() {
066: protected Object getAttribute(String key) {
067: return context.getAttribute(key);
068: }
069:
070: protected void setAttribute(String key, Object value) {
071: context.setAttribute(key, value);
072: }
073:
074: protected void removeAttribute(String key) {
075: context.removeAttribute(key);
076: }
077:
078: protected Enumeration getAttributeNames() {
079: return context.getAttributeNames();
080: }
081: };
082: this .sessionMap = new AbstractAttributeMap() {
083: protected Object getAttribute(String key) {
084: return session.getAttribute(key);
085: }
086:
087: protected void setAttribute(String key, Object value) {
088: session.setAttribute(key, value);
089: }
090:
091: protected void removeAttribute(String key) {
092: session.removeAttribute(key);
093: }
094:
095: protected Enumeration getAttributeNames() {
096: return session.getAttributeNames();
097: }
098: };
099: this .requestMap = new RequestAttributeMap();
100: this .requestCookieMap = new HashMap();
101:
102: this .update(this .request, this .response);
103: this .insertNewViewrootToken();
104: // #ICE-1722 default to normal mode before the first request
105: switchToNormalMode();
106: }
107:
108: public Object getSession(boolean create) {
109: return session;
110: }
111:
112: public Object getContext() {
113: return context;
114: }
115:
116: public Object getRequest() {
117: return request;
118: }
119:
120: public Object getResponse() {
121: return response;
122: }
123:
124: public void update(HttpServletRequest request,
125: HttpServletResponse response) {
126: //update parameters
127: boolean persistSeamKey = isSeamLifecycleShortcut();
128:
129: requestParameterMap = Collections
130: .synchronizedMap(new HashMap());
131: requestParameterValuesMap = Collections
132: .synchronizedMap(new HashMap());
133: insertPostbackKey();
134: Enumeration parameterNames = request.getParameterNames();
135: while (parameterNames.hasMoreElements()) {
136: String name = (String) parameterNames.nextElement();
137: Object value = request.getParameter(name);
138: requestParameterMap.put(name, value);
139: requestParameterValuesMap.put(name, request
140: .getParameterValues(name));
141: }
142:
143: applySeamLifecycleShortcut(persistSeamKey);
144:
145: requestCookieMap = Collections.synchronizedMap(new HashMap());
146: Cookie[] cookies = request.getCookies();
147: if (cookies != null) {
148: for (int i = 0; i < cookies.length; i++) {
149: Cookie cookie = cookies[i];
150: requestCookieMap.put(cookie.getName(), cookie);
151: }
152: }
153: responseCookieMap = Collections.synchronizedMap(new HashMap());
154:
155: this .response = response;
156: }
157:
158: public void updateOnReload(Object request, Object response) {
159: Map previousRequestMap = this .requestMap;
160: this .request = (HttpServletRequest) request;
161: this .requestMap = new RequestAttributeMap();
162: //propagate entries
163: this .requestMap.putAll(previousRequestMap);
164: this .update((HttpServletRequest) request,
165: (HttpServletResponse) response);
166: }
167:
168: //todo: implement!
169: public Map getRequestHeaderMap() {
170: return Collections.EMPTY_MAP;
171: }
172:
173: //todo: implement!
174: public Map getRequestHeaderValuesMap() {
175: return Collections.EMPTY_MAP;
176: }
177:
178: public Locale getRequestLocale() {
179: return request.getLocale();
180: }
181:
182: public Iterator getRequestLocales() {
183: return new EnumerationIterator(request.getLocales());
184: }
185:
186: public String getRequestPathInfo() {
187: return convertEmptyStringToNull(requestPathInfo == null ? request
188: .getPathInfo()
189: : requestPathInfo);
190: }
191:
192: public String getRequestURI() {
193: String requestURI = (String) request
194: .getAttribute("javax.servlet.forward.request_uri");
195: return requestURI == null ? request.getRequestURI()
196: : requestURI;
197: }
198:
199: public String getRequestContextPath() {
200: String contextPath = (String) request
201: .getAttribute("javax.servlet.forward.context_path");
202: return contextPath == null ? request.getContextPath()
203: : contextPath;
204: }
205:
206: public String getRequestServletPath() {
207: //crazy "workaround": solves the different behaviour MyFaces and Icefaces (including Sun-RI) need from this method
208: boolean callFromMyfaces = new Exception().getStackTrace()[1]
209: .getClassName().startsWith("org.apache.myfaces");
210: if (callFromMyfaces) {
211: return requestServletPath == null ? request
212: .getServletPath() : requestServletPath;
213: } else {
214: String servletPath = (String) request
215: .getAttribute("javax.servlet.forward.servlet_path");
216: return servletPath == null ? request.getServletPath()
217: : servletPath;
218: }
219: }
220:
221: public Set getResourcePaths(String path) {
222: return context.getResourcePaths(path);
223: }
224:
225: public URL getResource(String path) throws MalformedURLException {
226: return context.getResource(path);
227: }
228:
229: public InputStream getResourceAsStream(String path) {
230: return context.getResourceAsStream(path);
231: }
232:
233: public String encodeActionURL(String url) {
234: return url;
235: }
236:
237: public String encodeResourceURL(String url) {
238: try {
239: return response.encodeURL(url);
240: } catch (Exception e) {
241: return url;
242: }
243: }
244:
245: public String encodeNamespace(String name) {
246: return name;
247: }
248:
249: public void dispatch(String path) throws IOException,
250: FacesException {
251: try {
252: request.getRequestDispatcher(path).forward(request,
253: response);
254: } catch (ServletException se) {
255: throw new FacesException(se);
256: }
257: }
258:
259: public void log(String message) {
260: context.log(message);
261: }
262:
263: public void log(String message, Throwable throwable) {
264: context.log(message, throwable);
265: }
266:
267: public String getAuthType() {
268: return request.getAuthType();
269: }
270:
271: public String getRemoteUser() {
272: return request.getRemoteUser();
273: }
274:
275: public Principal getUserPrincipal() {
276: return request.getUserPrincipal();
277: }
278:
279: public boolean isUserInRole(String role) {
280: return request.isUserInRole(role);
281: }
282:
283: public Writer getWriter(String encoding) throws IOException {
284: try {
285: return new OutputStreamWriter(response.getOutputStream(),
286: encoding);
287: } catch (IllegalStateException e) {
288: // getWriter() already called, perhaps because of JSP include
289: return response.getWriter();
290: }
291: }
292:
293: /**
294: * Switch to normal redirection mode, using the HTTPServletResponse object
295: */
296: public void switchToNormalMode() {
297: redirector = new Redirector() {
298: public void redirect(String uri) {
299: try {
300: response.sendRedirect(uri);
301: } catch (IOException e) {
302: throw new RuntimeException(e);
303: }
304: }
305: };
306:
307: cookieTransporter = new CookieTransporter() {
308: public void send(Cookie cookie) {
309: response.addCookie(cookie);
310: }
311: };
312: }
313:
314: public void switchToPushMode() {
315: redirector = new CommandQueueRedirector();
316: cookieTransporter = new CommandQueueCookieTransporter();
317: resetRequestMap();
318: }
319:
320: private class RequestAttributeMap extends
321: AbstractCopyingAttributeMap {
322: public Enumeration getAttributeNames() {
323: return request.getAttributeNames();
324: }
325:
326: public Object getAttribute(String name) {
327: return request.getAttribute(name);
328: }
329:
330: public void setAttribute(String name, Object value) {
331: request.setAttribute(name, value);
332: }
333:
334: public void removeAttribute(String name) {
335: request.removeAttribute(name);
336: }
337: }
338:
339: /**
340: * Utility method that returns the original value of the supplied String
341: * unless it is emtpy (val.trim().length() == 0). In that particlar case
342: * the value returned is null.
343: *
344: * @param val
345: * @return
346: */
347: private static String convertEmptyStringToNull(String val) {
348: return val == null || val.trim().length() == 0 ? null : val;
349: }
350:
351: public class InterceptingHttpSession extends ProxyHttpSession {
352: private final SessionDispatcher.Listener.Monitor sessionMonitor;
353:
354: public InterceptingHttpSession(HttpSession session,
355: SessionDispatcher.Listener.Monitor sessionMonitor) {
356: super (session);
357: this .sessionMonitor = sessionMonitor;
358: }
359:
360: public void invalidate() {
361: sessionMonitor.shutdown();
362: }
363: }
364: }
|