KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > web > context > request > ServletRequestAttributes


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.web.context.request;
18
19 import java.io.Serializable JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.Map JavaDoc;
23
24 import javax.servlet.http.HttpServletRequest JavaDoc;
25 import javax.servlet.http.HttpSession JavaDoc;
26 import javax.servlet.http.HttpSessionBindingEvent JavaDoc;
27 import javax.servlet.http.HttpSessionBindingListener JavaDoc;
28
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
31
32 import org.springframework.util.Assert;
33 import org.springframework.util.ClassUtils;
34 import org.springframework.web.util.WebUtils;
35
36 /**
37  * Servlet-based implementation of the {@link RequestAttributes} interface.
38  * <p>Accesses objects from servlet request and HTTP session scope,
39  * with no distinction between "session" and "global session".
40  *
41  * @author Juergen Hoeller
42  * @since 2.0
43  * @see javax.servlet.ServletRequest#getAttribute
44  * @see javax.servlet.http.HttpSession#getAttribute
45  */

46 public class ServletRequestAttributes extends AbstractRequestAttributes {
47
48     /**
49      * Constant identifying the {@link String} prefixed to the name of a
50      * destruction callback when it is stored in a {@link HttpSession}.
51      */

52     public static final String JavaDoc DESTRUCTION_CALLBACK_NAME_PREFIX =
53             ServletRequestAttributes.class.getName() + ".DESTRUCTION_CALLBACK.";
54
55     // We'll create a lot of these objects, so we don't want a new logger every time.
56
private static final Log logger = LogFactory.getLog(ServletRequestAttributes.class);
57
58     // Determine whether Servlet 2.3's HttpSessionBindingListener interface is available.
59
private final static boolean bindingListenerAvailable =
60             ClassUtils.isPresent(
61                     "javax.servlet.http.HttpSessionBindingListener", ServletRequestAttributes.class.getClassLoader());
62
63
64     private final HttpServletRequest JavaDoc request;
65
66     private HttpSession JavaDoc session;
67
68     private final Map JavaDoc sessionAttributesToUpdate = new HashMap JavaDoc();
69
70
71     /**
72      * Create a new ServletRequestAttributes instance for the given request.
73      * @param request current HTTP request
74      */

75     public ServletRequestAttributes(HttpServletRequest JavaDoc request) {
76         Assert.notNull(request, "Request must not be null");
77         this.request = request;
78         // Fetch existing session reference early, to have it available even
79
// after request completion (for example, in a custom child thread).
80
this.session = request.getSession(false);
81     }
82
83
84     /**
85      * Exposes the {@link HttpServletRequest} that we're wrapping.
86      */

87     protected final HttpServletRequest JavaDoc getRequest() {
88         return this.request;
89     }
90
91     /**
92      * Exposes the {@link HttpSession} that we're wrapping.
93      * @param allowCreate whether to allow creation of a new session if none exists yet
94      */

95     protected final HttpSession JavaDoc getSession(boolean allowCreate) {
96         try {
97             this.session = this.request.getSession(allowCreate);
98             return this.session;
99         }
100         catch (IllegalStateException JavaDoc ex) {
101             // Couldn't access session... let's check why.
102
if (this.session == null) {
103                 // No matter what happened - we cannot offer a session.
104
throw ex;
105             }
106             // We have a fallback session reference...
107
// Let's see whether it is appropriate to return it.
108
if (allowCreate) {
109                 boolean canAskForExistingSession = false;
110                 try {
111                     this.session = this.request.getSession(false);
112                     canAskForExistingSession = true;
113                 }
114                 catch (IllegalStateException JavaDoc ex2) {
115                 }
116                 if (canAskForExistingSession) {
117                     // Could ask for existing session, hence the IllegalStateException
118
// came from trying to create a new session too late -> rethrow.
119
throw ex;
120                 }
121             }
122             // Else: Could not even ask for existing session, hence we assume that
123
// the request has been completed and the session is accessed later on
124
// (for example, in a custom child thread).
125
return this.session;
126         }
127     }
128
129
130     public Object JavaDoc getAttribute(String JavaDoc name, int scope) {
131         if (scope == SCOPE_REQUEST) {
132             return this.request.getAttribute(name);
133         }
134         else {
135             HttpSession JavaDoc session = getSession(false);
136             if (session != null) {
137                 Object JavaDoc value = session.getAttribute(name);
138                 if (value != null) {
139                     this.sessionAttributesToUpdate.put(name, value);
140                 }
141                 return value;
142             }
143             else {
144                 return null;
145             }
146         }
147     }
148
149     public void setAttribute(String JavaDoc name, Object JavaDoc value, int scope) {
150         if (scope == SCOPE_REQUEST) {
151             this.request.setAttribute(name, value);
152         }
153         else {
154             HttpSession JavaDoc session = getSession(true);
155             session.setAttribute(name, value);
156             this.sessionAttributesToUpdate.remove(name);
157         }
158     }
159
160     public void removeAttribute(String JavaDoc name, int scope) {
161         if (scope == SCOPE_REQUEST) {
162             this.request.removeAttribute(name);
163             removeRequestDestructionCallback(name);
164         }
165         else {
166             HttpSession JavaDoc session = getSession(false);
167             if (session != null) {
168                 session.removeAttribute(name);
169                 this.sessionAttributesToUpdate.remove(name);
170                 // Remove any registered destruction callback as well.
171
session.removeAttribute(DESTRUCTION_CALLBACK_NAME_PREFIX + name);
172             }
173         }
174     }
175
176     public void registerDestructionCallback(String JavaDoc name, Runnable JavaDoc callback, int scope) {
177         if (scope == SCOPE_REQUEST) {
178             registerRequestDestructionCallback(name, callback);
179         }
180         else {
181             registerSessionDestructionCallback(name, callback);
182         }
183     }
184
185     public String JavaDoc getSessionId() {
186         return getSession(true).getId();
187     }
188
189     public Object JavaDoc getSessionMutex() {
190         return WebUtils.getSessionMutex(getSession(true));
191     }
192
193
194     /**
195      * Update all accessed session attributes through <code>session.setAttribute</code>
196      * calls, explicitly indicating to the container that they might have been modified.
197      */

198     protected void updateAccessedSessionAttributes() {
199         HttpSession JavaDoc session = getSession(false);
200         if (session != null) {
201             for (Iterator JavaDoc it = this.sessionAttributesToUpdate.entrySet().iterator(); it.hasNext();) {
202                 Map.Entry JavaDoc entry = (Map.Entry JavaDoc) it.next();
203                 String JavaDoc name = (String JavaDoc) entry.getKey();
204                 Object JavaDoc newValue = entry.getValue();
205                 Object JavaDoc oldValue = session.getAttribute(name);
206                 if (oldValue == newValue) {
207                     session.setAttribute(name, newValue);
208                 }
209             }
210         }
211         this.sessionAttributesToUpdate.clear();
212     }
213
214     /**
215      * Register the given callback as to be executed after session termination.
216      * @param name the name of the attribute to register the callback for
217      * @param callback the callback to be executed for destruction
218      */

219     private void registerSessionDestructionCallback(String JavaDoc name, Runnable JavaDoc callback) {
220         if (bindingListenerAvailable) {
221             HttpSession JavaDoc session = getSession(true);
222             session.setAttribute(DESTRUCTION_CALLBACK_NAME_PREFIX + name,
223                     new DestructionCallbackBindingListener(callback));
224         }
225         else {
226             if (logger.isWarnEnabled()) {
227                 logger.warn("Could not register destruction callback [" + callback + "] for attribute '" +
228                         name + "' in session scope because Servlet 2.3 API is not available");
229             }
230         }
231     }
232
233
234     /**
235      * Adapter that implements the Servlet 2.3 HttpSessionBindingListener
236      * interface, wrapping a request destruction callback.
237      */

238     private static class DestructionCallbackBindingListener implements HttpSessionBindingListener JavaDoc, Serializable JavaDoc {
239
240         private final Runnable JavaDoc destructionCallback;
241
242         public DestructionCallbackBindingListener(Runnable JavaDoc destructionCallback) {
243             this.destructionCallback = destructionCallback;
244         }
245
246         public void valueBound(HttpSessionBindingEvent JavaDoc event) {
247         }
248
249         public void valueUnbound(HttpSessionBindingEvent JavaDoc event) {
250             this.destructionCallback.run();
251         }
252     }
253
254 }
255
Popular Tags