|
|||||||||||||||||||
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover | |||||||||||||||||||
Source file | Conditionals | Statements | Methods | TOTAL | |||||||||||||||
RequestContext.java | 60.7% | 80% | 83.7% | 75.7% |
|
1 |
// Copyright 2004, 2005 The Apache Software Foundation
|
|
2 |
//
|
|
3 |
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4 |
// you may not use this file except in compliance with the License.
|
|
5 |
// You may obtain a copy of the License at
|
|
6 |
//
|
|
7 |
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8 |
//
|
|
9 |
// Unless required by applicable law or agreed to in writing, software
|
|
10 |
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11 |
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12 |
// See the License for the specific language governing permissions and
|
|
13 |
// limitations under the License.
|
|
14 |
|
|
15 |
package org.apache.tapestry.request;
|
|
16 |
|
|
17 |
import java.io.IOException;
|
|
18 |
import java.util.ArrayList;
|
|
19 |
import java.util.Collections;
|
|
20 |
import java.util.Date;
|
|
21 |
import java.util.Enumeration;
|
|
22 |
import java.util.HashMap;
|
|
23 |
import java.util.List;
|
|
24 |
import java.util.Map;
|
|
25 |
import java.util.Properties;
|
|
26 |
import java.util.StringTokenizer;
|
|
27 |
|
|
28 |
import javax.servlet.ServletConfig;
|
|
29 |
import javax.servlet.ServletContext;
|
|
30 |
import javax.servlet.http.Cookie;
|
|
31 |
import javax.servlet.http.HttpServlet;
|
|
32 |
import javax.servlet.http.HttpServletRequest;
|
|
33 |
import javax.servlet.http.HttpServletResponse;
|
|
34 |
import javax.servlet.http.HttpSession;
|
|
35 |
|
|
36 |
import org.apache.commons.logging.Log;
|
|
37 |
import org.apache.commons.logging.LogFactory;
|
|
38 |
import org.apache.tapestry.ApplicationServlet;
|
|
39 |
import org.apache.tapestry.IMarkupWriter;
|
|
40 |
import org.apache.tapestry.IRender;
|
|
41 |
import org.apache.tapestry.IRequestCycle;
|
|
42 |
import org.apache.tapestry.Tapestry;
|
|
43 |
import org.apache.tapestry.multipart.DefaultMultipartDecoder;
|
|
44 |
import org.apache.tapestry.multipart.IMultipartDecoder;
|
|
45 |
import org.apache.tapestry.spec.IApplicationSpecification;
|
|
46 |
|
|
47 |
/**
|
|
48 |
* This class encapsulates all the relevant data for one request cycle of an
|
|
49 |
* {@link ApplicationServlet}. This includes:
|
|
50 |
* <ul>
|
|
51 |
* <li>{@link HttpServletRequest}
|
|
52 |
* <li>{@link HttpServletResponse}
|
|
53 |
* <li>{@link HttpSession}
|
|
54 |
* <li>{@link javax.servlet.http.HttpServlet}
|
|
55 |
* </ul>
|
|
56 |
* <p>
|
|
57 |
* It also provides methods for:
|
|
58 |
* <ul>
|
|
59 |
* <li>Retrieving the request parameters (even if a file upload is involved)
|
|
60 |
* <li>Getting, setting and removing request attributes
|
|
61 |
* <li>Forwarding requests
|
|
62 |
* <li>Redirecting requests
|
|
63 |
* <li>Getting and setting Cookies
|
|
64 |
* <li>Intepreting the request path info
|
|
65 |
* <li>Writing an HTML description of the <code>RequestContext</code> (for debugging).
|
|
66 |
* </ul>
|
|
67 |
* <p>
|
|
68 |
* If some cases, it is necesary to provide an implementation of {@link IRequestDecoder}(often, due
|
|
69 |
* to a firewall). If the application specifification provides an extension named
|
|
70 |
* <code>org.apache.tapestry.request-decoder</code> then it will be used, instead of a default
|
|
71 |
* decoder.
|
|
72 |
* <p>
|
|
73 |
* This class is not a component, but does implement {@link IRender}. When asked to render (perhaps
|
|
74 |
* as the delegate of a {@link org.apache.tapestry.components.Delegator}component} it simply
|
|
75 |
* invokes {@link #write(IMarkupWriter)}to display all debugging output.
|
|
76 |
* <p>
|
|
77 |
* This class is derived from the original class <code>com.primix.servlet.RequestContext</code>,
|
|
78 |
* part of the <b>ServletUtils </b> framework available from <a
|
|
79 |
* href="http://www.gjt.org/servlets/JCVSlet/list/gjt/com/primix/servlet">The Giant Java Tree </a>.
|
|
80 |
*
|
|
81 |
* @author Howard Lewis Ship
|
|
82 |
*/
|
|
83 |
|
|
84 |
public class RequestContext implements IRender |
|
85 |
{ |
|
86 |
/** @since 2.2 * */
|
|
87 |
|
|
88 |
private static class DefaultRequestDecoder implements IRequestDecoder |
|
89 |
{ |
|
90 | 185 |
public DecodedRequest decodeRequest(HttpServletRequest request)
|
91 |
{ |
|
92 | 185 |
DecodedRequest result = new DecodedRequest();
|
93 |
|
|
94 | 185 |
result.setRequestURI(request.getRequestURI()); |
95 | 185 |
result.setScheme(request.getScheme()); |
96 | 185 |
result.setServerName(request.getServerName()); |
97 | 185 |
result.setServerPort(request.getServerPort()); |
98 |
|
|
99 | 185 |
return result;
|
100 |
} |
|
101 |
} |
|
102 |
|
|
103 |
private static final Log LOG = LogFactory.getLog(RequestContext.class); |
|
104 |
|
|
105 |
private HttpSession _session;
|
|
106 |
|
|
107 |
private HttpServletRequest _request;
|
|
108 |
|
|
109 |
private HttpServletResponse _response;
|
|
110 |
|
|
111 |
private HttpServlet _servlet;
|
|
112 |
|
|
113 |
private DecodedRequest _decodedRequest;
|
|
114 |
|
|
115 |
private IMultipartDecoder _decoder;
|
|
116 |
|
|
117 |
private boolean _decoded; |
|
118 |
|
|
119 |
private IApplicationSpecification _specification;
|
|
120 |
|
|
121 |
/**
|
|
122 |
* A mapping of the cookies available in the request.
|
|
123 |
*/
|
|
124 |
|
|
125 |
private Map _cookieMap;
|
|
126 |
|
|
127 |
/**
|
|
128 |
* Used during {@link #write(IMarkupWriter)}.
|
|
129 |
*/
|
|
130 |
|
|
131 |
private boolean _evenRow; |
|
132 |
|
|
133 |
/**
|
|
134 |
* Creates a <code>RequestContext</code> from its components.
|
|
135 |
*/
|
|
136 |
|
|
137 | 187 |
public RequestContext(HttpServlet servlet, HttpServletRequest request,
|
138 |
HttpServletResponse response, IApplicationSpecification specification) |
|
139 |
throws IOException
|
|
140 |
{ |
|
141 | 187 |
_servlet = servlet; |
142 | 187 |
_request = request; |
143 | 187 |
_response = response; |
144 | 187 |
_specification = specification; |
145 |
|
|
146 |
// All three parameters may be null if created from
|
|
147 |
// AbstractEngine.cleanupEngine().
|
|
148 |
|
|
149 | 187 |
if (_request != null && DefaultMultipartDecoder.isMultipartRequest(request)) |
150 |
{ |
|
151 | 6 |
IMultipartDecoder decoder = obtainMultipartDecoder(servlet, request); |
152 | 6 |
setDecoder(decoder); |
153 |
} |
|
154 |
} |
|
155 |
|
|
156 |
/**
|
|
157 |
* Invoked from the constructor to create a {@link DefaultMultipartDecoder}instance.
|
|
158 |
* Applications with specific upload needs may need to override this to provide a subclass
|
|
159 |
* instance instead. The caller will invoke {@link IMultipartDecoder#decode(HttpServletRequest)}
|
|
160 |
* on the returned object.
|
|
161 |
* <p>
|
|
162 |
* This implementation checks for application extension
|
|
163 |
* {@link Tapestry#MULTIPART_DECODER_EXTENSION_NAME}. If that is not defined, a shared instance
|
|
164 |
* of {@link DefaultMultipartDecoder}is returned.
|
|
165 |
*
|
|
166 |
* @see ApplicationServlet#createRequestContext(HttpServletRequest, HttpServletResponse)
|
|
167 |
* @since 3.0
|
|
168 |
*/
|
|
169 |
|
|
170 | 6 |
protected IMultipartDecoder obtainMultipartDecoder(HttpServlet servlet,
|
171 |
HttpServletRequest request) throws IOException
|
|
172 |
{ |
|
173 | 6 |
if (_specification.checkExtension(Tapestry.MULTIPART_DECODER_EXTENSION_NAME))
|
174 | 6 |
return (IMultipartDecoder) _specification.getExtension(
|
175 |
Tapestry.MULTIPART_DECODER_EXTENSION_NAME, |
|
176 |
IMultipartDecoder.class);
|
|
177 |
|
|
178 | 0 |
return DefaultMultipartDecoder.getSharedInstance();
|
179 |
} |
|
180 |
|
|
181 |
/**
|
|
182 |
* Adds a simple {@link Cookie}. To set a Cookie with attributes, use
|
|
183 |
* {@link #addCookie(Cookie)}.
|
|
184 |
*/
|
|
185 |
|
|
186 | 0 |
public void addCookie(String name, String value) |
187 |
{ |
|
188 | 0 |
addCookie(new Cookie(name, value));
|
189 |
} |
|
190 |
|
|
191 |
/**
|
|
192 |
* Adds a {@link Cookie}to the response. Once added, the Cookie will also be available to
|
|
193 |
* {@link #getCookie(String)}method.
|
|
194 |
* <p>
|
|
195 |
* Cookies should only be added <em>before</em> invoking
|
|
196 |
* {@link HttpServletResponse#getWriter()}..
|
|
197 |
*/
|
|
198 |
|
|
199 | 0 |
public void addCookie(Cookie cookie) |
200 |
{ |
|
201 | 0 |
if (LOG.isDebugEnabled())
|
202 | 0 |
LOG.debug("Adding cookie " + cookie);
|
203 |
|
|
204 | 0 |
_response.addCookie(cookie); |
205 |
|
|
206 | 0 |
if (_cookieMap == null) |
207 | 0 |
readCookieMap(); |
208 |
|
|
209 | 0 |
_cookieMap.put(cookie.getName(), cookie); |
210 |
} |
|
211 |
|
|
212 | 18 |
private void datePair(IMarkupWriter writer, String name, long value) |
213 |
{ |
|
214 | 18 |
pair(writer, name, new Date(value));
|
215 |
} |
|
216 |
|
|
217 |
/** @since 2.2 * */
|
|
218 |
|
|
219 | 704 |
private DecodedRequest getDecodedRequest()
|
220 |
{ |
|
221 | 704 |
if (_decodedRequest != null) |
222 | 519 |
return _decodedRequest;
|
223 |
|
|
224 | 185 |
IRequestDecoder decoder = null;
|
225 |
|
|
226 | 185 |
if (!_specification.checkExtension(Tapestry.REQUEST_DECODER_EXTENSION_NAME))
|
227 | 185 |
decoder = new DefaultRequestDecoder();
|
228 |
else
|
|
229 | 0 |
decoder = (IRequestDecoder) _specification.getExtension( |
230 |
Tapestry.REQUEST_DECODER_EXTENSION_NAME, |
|
231 |
IRequestDecoder.class);
|
|
232 |
|
|
233 | 185 |
_decodedRequest = decoder.decodeRequest(_request); |
234 |
|
|
235 | 185 |
return _decodedRequest;
|
236 |
} |
|
237 |
|
|
238 |
/**
|
|
239 |
* Returns the actual scheme, possibly decoded from the request.
|
|
240 |
*
|
|
241 |
* @see IRequestDecoder
|
|
242 |
* @see javax.servlet.ServletRequest#getScheme()
|
|
243 |
* @since 2.2
|
|
244 |
*/
|
|
245 |
|
|
246 | 173 |
public String getScheme()
|
247 |
{ |
|
248 | 173 |
return getDecodedRequest().getScheme();
|
249 |
} |
|
250 |
|
|
251 |
/**
|
|
252 |
* Returns the actual server name, possibly decoded from the request.
|
|
253 |
*
|
|
254 |
* @see IRequestDecoder
|
|
255 |
* @see javax.servlet.ServletRequest#getServerName()
|
|
256 |
* @since 2.2
|
|
257 |
*/
|
|
258 |
|
|
259 | 173 |
public String getServerName()
|
260 |
{ |
|
261 | 173 |
return getDecodedRequest().getServerName();
|
262 |
} |
|
263 |
|
|
264 |
/**
|
|
265 |
* Returns the actual server port, possibly decoded from the request.
|
|
266 |
*
|
|
267 |
* @see IRequestDecoder
|
|
268 |
* @see javax.servlet.ServletRequest#getServerPort()
|
|
269 |
* @since 2.2
|
|
270 |
*/
|
|
271 |
|
|
272 | 173 |
public int getServerPort() |
273 |
{ |
|
274 | 173 |
return getDecodedRequest().getServerPort();
|
275 |
} |
|
276 |
|
|
277 |
/**
|
|
278 |
* Returns the actual request URI, possibly decoded from the request.
|
|
279 |
*
|
|
280 |
* @see IRequestDecoder
|
|
281 |
* @see HttpServletRequest#getRequestURI()
|
|
282 |
* @since 2.2
|
|
283 |
*/
|
|
284 |
|
|
285 | 185 |
public String getRequestURI()
|
286 |
{ |
|
287 | 185 |
return getDecodedRequest().getRequestURI();
|
288 |
} |
|
289 |
|
|
290 |
/**
|
|
291 |
* Builds an absolute URL from the given URI, using the {@link HttpServletRequest}as the source
|
|
292 |
* for scheme, server name and port.
|
|
293 |
*
|
|
294 |
* @see #getAbsoluteURL(String, String, String, int)
|
|
295 |
*/
|
|
296 |
|
|
297 | 172 |
public String getAbsoluteURL(String URI)
|
298 |
{ |
|
299 | 172 |
String scheme = getScheme(); |
300 | 172 |
String server = getServerName(); |
301 | 172 |
int port = getServerPort();
|
302 |
|
|
303 |
// Keep things simple ... port 80 is accepted as the
|
|
304 |
// standard port for http so it can be ommitted.
|
|
305 |
// Some of the Tomcat code indicates that port 443 is the default
|
|
306 |
// for https, and that needs to be researched.
|
|
307 |
|
|
308 | 172 |
if (scheme.equals("http") && port == 80) |
309 | 172 |
port = 0; |
310 |
|
|
311 | 172 |
return getAbsoluteURL(URI, scheme, server, port);
|
312 |
} |
|
313 |
|
|
314 |
/**
|
|
315 |
* Does some easy checks to turn a path (or URI) into an absolute URL. We assume
|
|
316 |
* <ul>
|
|
317 |
* <li>The presense of a colon means the path is complete already (any other colons in the URI
|
|
318 |
* portion should have been converted to %3A).
|
|
319 |
* <li>A leading pair of forward slashes means the path is simply missing the scheme.
|
|
320 |
* <li>Otherwise, we assemble the scheme, server, port (if non-zero) and the URI as given.
|
|
321 |
* </ul>
|
|
322 |
*/
|
|
323 |
|
|
324 | 172 |
public String getAbsoluteURL(String URI, String scheme, String server, int port) |
325 |
{ |
|
326 | 172 |
StringBuffer buffer = new StringBuffer();
|
327 |
|
|
328 |
// Though, really, what does a leading colon with no scheme before it
|
|
329 |
// mean?
|
|
330 |
|
|
331 | 172 |
if (URI.indexOf(':') >= 0)
|
332 | 0 |
return URI;
|
333 |
|
|
334 |
// Should check the length here, first.
|
|
335 |
|
|
336 | 172 |
if (URI.substring(0, 1).equals("//")) |
337 |
{ |
|
338 | 0 |
buffer.append(scheme); |
339 | 0 |
buffer.append(':'); |
340 | 0 |
buffer.append(URI); |
341 | 0 |
return buffer.toString();
|
342 |
} |
|
343 |
|
|
344 | 172 |
buffer.append(scheme); |
345 | 172 |
buffer.append("://");
|
346 | 172 |
buffer.append(server); |
347 |
|
|
348 | 172 |
if (port > 0)
|
349 |
{ |
|
350 | 0 |
buffer.append(':'); |
351 | 0 |
buffer.append(port); |
352 |
} |
|
353 |
|
|
354 | 172 |
if (URI.charAt(0) != '/')
|
355 | 0 |
buffer.append('/'); |
356 |
|
|
357 | 172 |
buffer.append(URI); |
358 |
|
|
359 | 172 |
return buffer.toString();
|
360 |
} |
|
361 |
|
|
362 |
/**
|
|
363 |
* Gets a named {@link Cookie}.
|
|
364 |
*
|
|
365 |
* @param name
|
|
366 |
* The name of the Cookie.
|
|
367 |
* @return The Cookie, or null if no Cookie with that name exists.
|
|
368 |
*/
|
|
369 |
|
|
370 | 0 |
public Cookie getCookie(String name)
|
371 |
{ |
|
372 | 0 |
if (_cookieMap == null) |
373 | 0 |
readCookieMap(); |
374 |
|
|
375 | 0 |
return (Cookie) _cookieMap.get(name);
|
376 |
} |
|
377 |
|
|
378 |
/**
|
|
379 |
* Reads the named {@link Cookie}and returns its value (if it exists), or null if it does not
|
|
380 |
* exist.
|
|
381 |
*/
|
|
382 |
|
|
383 | 0 |
public String getCookieValue(String name)
|
384 |
{ |
|
385 | 0 |
Cookie cookie; |
386 |
|
|
387 | 0 |
cookie = getCookie(name); |
388 |
|
|
389 | 0 |
if (cookie == null) |
390 | 0 |
return null; |
391 |
|
|
392 | 0 |
return cookie.getValue();
|
393 |
} |
|
394 |
|
|
395 |
/**
|
|
396 |
* Returns the named parameter from the {@link HttpServletRequest}.
|
|
397 |
* <p>
|
|
398 |
* Use {@link #getParameters(String)}for parameters that may include multiple values.
|
|
399 |
* <p>
|
|
400 |
* This is the preferred way to obtain parameter values (rather than obtaining the
|
|
401 |
* {@link HttpServletRequest}itself). For form/multipart-data encoded requests, this method
|
|
402 |
* will still work.
|
|
403 |
*/
|
|
404 |
|
|
405 | 49 |
public String getParameter(String name)
|
406 |
{ |
|
407 | 49 |
IMultipartDecoder decoder = getDecoder(); |
408 | 49 |
if (decoder != null) |
409 | 0 |
return decoder.getString(_request, name);
|
410 |
|
|
411 | 49 |
return _request.getParameter(name);
|
412 |
} |
|
413 |
|
|
414 |
/**
|
|
415 |
* Convienience method for getting a {@link HttpServletRequest}attribute.
|
|
416 |
*
|
|
417 |
* @since 2.3
|
|
418 |
*/
|
|
419 |
|
|
420 | 60 |
public Object getAttribute(String name)
|
421 |
{ |
|
422 | 60 |
return _request.getAttribute(name);
|
423 |
} |
|
424 |
|
|
425 |
/**
|
|
426 |
* For parameters that are, or are possibly, multi-valued, this method returns all the values as
|
|
427 |
* an array of Strings.
|
|
428 |
*
|
|
429 |
* @see #getParameter(String)
|
|
430 |
*/
|
|
431 |
|
|
432 | 589 |
public String[] getParameters(String name)
|
433 |
{ |
|
434 | 589 |
IMultipartDecoder decoder = getDecoder(); |
435 | 589 |
if (decoder != null) |
436 | 30 |
return decoder.getStrings(_request, name);
|
437 |
|
|
438 | 559 |
return _request.getParameterValues(name);
|
439 |
} |
|
440 |
|
|
441 | 185 |
public String[] getParameterNames()
|
442 |
{ |
|
443 | 185 |
IMultipartDecoder decoder = getDecoder(); |
444 | 185 |
if (decoder != null) |
445 | 6 |
return decoder.getStringParameterNames(_request);
|
446 |
|
|
447 | 179 |
Enumeration e = _request.getParameterNames(); |
448 | 179 |
List names = new ArrayList();
|
449 |
|
|
450 | 179 |
while (e.hasMoreElements())
|
451 | 553 |
names.add(e.nextElement()); |
452 |
|
|
453 | 179 |
int count = names.size();
|
454 |
|
|
455 | 179 |
String[] result = new String[count];
|
456 |
|
|
457 | 179 |
return (String[]) names.toArray(result);
|
458 |
} |
|
459 |
|
|
460 |
/**
|
|
461 |
* Returns the named {@link IUploadFile}, if it exists, or null if it doesn't. Uploads require
|
|
462 |
* an encoding of <code>multipart/form-data</code> (this is specified in the form's enctype
|
|
463 |
* attribute). If the encoding type is not so, or if no upload matches the name, then this
|
|
464 |
* method returns null.
|
|
465 |
*/
|
|
466 |
|
|
467 | 3 |
public IUploadFile getUploadFile(String name)
|
468 |
{ |
|
469 | 3 |
IMultipartDecoder decoder = getDecoder(); |
470 | 3 |
if (decoder == null) |
471 | 0 |
return null; |
472 |
|
|
473 | 3 |
return decoder.getUploadFile(_request, name);
|
474 |
} |
|
475 |
|
|
476 |
/**
|
|
477 |
* Invoked at the end of the request cycle to cleanup and temporary resources. This is chained
|
|
478 |
* to the {@link DefaultMultipartDecoder}, if there is one.
|
|
479 |
*
|
|
480 |
* @since 2.0.1
|
|
481 |
*/
|
|
482 |
|
|
483 | 185 |
public void cleanup() |
484 |
{ |
|
485 | 185 |
if (_decoder != null) |
486 | 6 |
_decoder.cleanup(_request); |
487 |
} |
|
488 |
|
|
489 |
/**
|
|
490 |
* Returns the request which initiated the current request cycle. Note that the methods
|
|
491 |
* {@link #getParameter(String)}and {@link #getParameters(String)}should be used, rather than
|
|
492 |
* obtaining parameters directly from the request (since the RequestContext handles the
|
|
493 |
* differences between normal and multipart/form requests).
|
|
494 |
*/
|
|
495 |
|
|
496 | 375 |
public HttpServletRequest getRequest()
|
497 |
{ |
|
498 | 375 |
return _request;
|
499 |
} |
|
500 |
|
|
501 | 314 |
public HttpServletResponse getResponse()
|
502 |
{ |
|
503 | 314 |
return _response;
|
504 |
} |
|
505 |
|
|
506 | 2339 |
private String getRowClass()
|
507 |
{ |
|
508 | 2339 |
String result; |
509 |
|
|
510 | 2339 |
result = _evenRow ? "even" : "odd"; |
511 |
|
|
512 | 2339 |
_evenRow = !_evenRow; |
513 |
|
|
514 | 2339 |
return result;
|
515 |
} |
|
516 |
|
|
517 | 2 |
public HttpServlet getServlet()
|
518 |
{ |
|
519 | 2 |
return _servlet;
|
520 |
} |
|
521 |
|
|
522 |
/**
|
|
523 |
* Returns the {@link HttpSession}, if necessary, invoking
|
|
524 |
* {@link HttpServletRequest#getSession(boolean)}. However, this method will <em>not</em>
|
|
525 |
* create a session.
|
|
526 |
*/
|
|
527 |
|
|
528 | 37 |
public HttpSession getSession()
|
529 |
{ |
|
530 | 37 |
if (_session == null) |
531 | 34 |
_session = _request.getSession(false);
|
532 |
|
|
533 | 37 |
return _session;
|
534 |
} |
|
535 |
|
|
536 |
/**
|
|
537 |
* Like {@link #getSession()}, but forces the creation of the {@link HttpSession}, if
|
|
538 |
* necessary.
|
|
539 |
*/
|
|
540 |
|
|
541 | 0 |
public HttpSession createSession()
|
542 |
{ |
|
543 | 0 |
if (_session == null) |
544 |
{ |
|
545 | 0 |
if (LOG.isDebugEnabled())
|
546 | 0 |
LOG.debug("Creating HttpSession");
|
547 |
|
|
548 | 0 |
_session = _request.getSession(true);
|
549 |
} |
|
550 |
|
|
551 | 0 |
return _session;
|
552 |
} |
|
553 |
|
|
554 | 233 |
private void header(IMarkupWriter writer, String valueName, String dataName) |
555 |
{ |
|
556 | 233 |
writer.begin("tr");
|
557 | 233 |
writer.attribute("class", "request-context-header"); |
558 |
|
|
559 | 233 |
writer.begin("th");
|
560 | 233 |
writer.print(valueName); |
561 | 233 |
writer.end(); |
562 |
|
|
563 | 233 |
writer.begin("th");
|
564 | 233 |
writer.print(dataName); |
565 | 233 |
writer.end("tr");
|
566 |
|
|
567 | 233 |
_evenRow = true;
|
568 |
} |
|
569 |
|
|
570 | 145 |
private void object(IMarkupWriter writer, String objectName) |
571 |
{ |
|
572 | 145 |
writer.begin("span");
|
573 | 145 |
writer.attribute("class", "request-context-object"); |
574 | 145 |
writer.print(objectName); |
575 | 145 |
writer.end(); |
576 |
} |
|
577 |
|
|
578 | 145 |
private void pair(IMarkupWriter writer, String name, int value) |
579 |
{ |
|
580 | 145 |
pair(writer, name, Integer.toString(value)); |
581 |
} |
|
582 |
|
|
583 | 144 |
private void pair(IMarkupWriter writer, String name, Object value) |
584 |
{ |
|
585 | 144 |
if (value == null) |
586 | 34 |
return;
|
587 |
|
|
588 | 110 |
pair(writer, name, value.toString()); |
589 |
} |
|
590 |
|
|
591 | 2598 |
private void pair(IMarkupWriter writer, String name, String value) |
592 |
{ |
|
593 | 2598 |
if (value == null) |
594 | 340 |
return;
|
595 |
|
|
596 | 2258 |
if (value.length() == 0)
|
597 | 102 |
return;
|
598 |
|
|
599 | 2156 |
writer.begin("tr");
|
600 | 2156 |
writer.attribute("class", getRowClass());
|
601 |
|
|
602 | 2156 |
writer.begin("th");
|
603 | 2156 |
writer.print(name); |
604 | 2156 |
writer.end(); |
605 |
|
|
606 | 2156 |
writer.begin("td");
|
607 | 2156 |
writer.print(value); |
608 | 2156 |
writer.end("tr");
|
609 | 2156 |
writer.println(); |
610 |
} |
|
611 |
|
|
612 | 9 |
private void pair(IMarkupWriter writer, String name, boolean value) |
613 |
{ |
|
614 | 9 |
pair(writer, name, value ? "yes" : "no"); |
615 |
} |
|
616 |
|
|
617 | 0 |
private void readCookieMap() |
618 |
{ |
|
619 | 0 |
_cookieMap = new HashMap();
|
620 |
|
|
621 | 0 |
Cookie[] cookies = _request.getCookies(); |
622 |
|
|
623 | 0 |
if (cookies != null) |
624 | 0 |
for (int i = 0; i < cookies.length; i++) |
625 | 0 |
_cookieMap.put(cookies[i].getName(), cookies[i]); |
626 |
} |
|
627 |
|
|
628 | 199 |
private void section(IMarkupWriter writer, String sectionName) |
629 |
{ |
|
630 | 199 |
writer.begin("tr");
|
631 | 199 |
writer.attribute("class", "request-context-section"); |
632 | 199 |
writer.begin("th");
|
633 | 199 |
writer.attribute("colspan", 2);
|
634 |
|
|
635 | 199 |
writer.print(sectionName); |
636 | 199 |
writer.end("tr");
|
637 |
} |
|
638 |
|
|
639 | 213 |
private List getSorted(Enumeration e)
|
640 |
{ |
|
641 | 213 |
List result = new ArrayList();
|
642 |
|
|
643 |
// JDK 1.4 includes a helper method in Collections for
|
|
644 |
// this; but we want 1.2 compatibility for the
|
|
645 |
// forseable future.
|
|
646 |
|
|
647 | 213 |
while (e.hasMoreElements())
|
648 | 152 |
result.add(e.nextElement()); |
649 |
|
|
650 | 213 |
Collections.sort(result); |
651 |
|
|
652 | 213 |
return result;
|
653 |
} |
|
654 |
|
|
655 |
/**
|
|
656 |
* Writes the state of the context to the writer, typically for inclusion in a HTML page
|
|
657 |
* returned to the user. This is useful when debugging. The Inspector uses this as well.
|
|
658 |
*/
|
|
659 |
|
|
660 | 34 |
public void write(IMarkupWriter writer) |
661 |
{ |
|
662 |
// Create a box around all of this stuff ...
|
|
663 |
|
|
664 | 34 |
writer.begin("table");
|
665 | 34 |
writer.attribute("class", "request-context-border"); |
666 | 34 |
writer.begin("tr");
|
667 | 34 |
writer.begin("td");
|
668 |
|
|
669 |
// Get the session, if it exists, and display it.
|
|
670 |
|
|
671 | 34 |
HttpSession session = getSession(); |
672 |
|
|
673 | 34 |
if (session != null) |
674 |
{ |
|
675 | 9 |
object(writer, "Session");
|
676 | 9 |
writer.begin("table");
|
677 | 9 |
writer.attribute("class", "request-context-object"); |
678 |
|
|
679 | 9 |
section(writer, "Properties");
|
680 | 9 |
header(writer, "Name", "Value"); |
681 |
|
|
682 | 9 |
pair(writer, "id", session.getId());
|
683 | 9 |
datePair(writer, "creationTime", session.getCreationTime());
|
684 | 9 |
datePair(writer, "lastAccessedTime", session.getLastAccessedTime());
|
685 | 9 |
pair(writer, "maxInactiveInterval", session.getMaxInactiveInterval());
|
686 | 9 |
pair(writer, "new", session.isNew());
|
687 |
|
|
688 | 9 |
List names = getSorted(session.getAttributeNames()); |
689 | 9 |
int count = names.size();
|
690 |
|
|
691 | 9 |
for (int i = 0; i < count; i++) |
692 |
{ |
|
693 | 24 |
if (i == 0)
|
694 |
{ |
|
695 | 9 |
section(writer, "Attributes");
|
696 | 9 |
header(writer, "Name", "Value"); |
697 |
} |
|
698 |
|
|
699 | 24 |
String name = (String) names.get(i); |
700 | 24 |
pair(writer, name, session.getAttribute(name)); |
701 |
} |
|
702 |
|
|
703 | 9 |
writer.end(); // Session
|
704 |
|
|
705 |
} |
|
706 |
|
|
707 | 34 |
object(writer, "Request");
|
708 | 34 |
writer.begin("table");
|
709 | 34 |
writer.attribute("class", "request-context-object"); |
710 |
|
|
711 |
// Parameters ...
|
|
712 |
|
|
713 | 34 |
List parameters = getSorted(_request.getParameterNames()); |
714 | 34 |
int count = parameters.size();
|
715 |
|
|
716 | 34 |
for (int i = 0; i < count; i++) |
717 |
{ |
|
718 |
|
|
719 | 81 |
if (i == 0)
|
720 |
{ |
|
721 | 33 |
section(writer, "Parameters");
|
722 | 33 |
header(writer, "Name", "Value(s)"); |
723 |
} |
|
724 |
|
|
725 | 81 |
String name = (String) parameters.get(i); |
726 | 81 |
String[] values = _request.getParameterValues(name); |
727 |
|
|
728 | 81 |
writer.begin("tr");
|
729 | 81 |
writer.attribute("class", getRowClass());
|
730 | 81 |
writer.begin("th");
|
731 | 81 |
writer.print(name); |
732 | 81 |
writer.end(); |
733 | 81 |
writer.begin("td");
|
734 |
|
|
735 | 81 |
if (values.length > 1)
|
736 | 1 |
writer.begin("ul");
|
737 |
|
|
738 | 81 |
for (int j = 0; j < values.length; j++) |
739 |
{ |
|
740 | 83 |
if (values.length > 1)
|
741 | 3 |
writer.beginEmpty("li");
|
742 |
|
|
743 | 83 |
writer.print(values[j]); |
744 |
|
|
745 |
} |
|
746 |
|
|
747 | 81 |
writer.end("tr");
|
748 |
} |
|
749 |
|
|
750 | 34 |
section(writer, "Properties");
|
751 | 34 |
header(writer, "Name", "Value"); |
752 |
|
|
753 | 34 |
pair(writer, "authType", _request.getAuthType());
|
754 | 34 |
pair(writer, "characterEncoding", _request.getCharacterEncoding());
|
755 | 34 |
pair(writer, "contentLength", _request.getContentLength());
|
756 | 34 |
pair(writer, "contentType", _request.getContentType());
|
757 | 34 |
pair(writer, "method", _request.getMethod());
|
758 | 34 |
pair(writer, "pathInfo", _request.getPathInfo());
|
759 | 34 |
pair(writer, "pathTranslated", _request.getPathTranslated());
|
760 | 34 |
pair(writer, "protocol", _request.getProtocol());
|
761 | 34 |
pair(writer, "queryString", _request.getQueryString());
|
762 | 34 |
pair(writer, "remoteAddr", _request.getRemoteAddr());
|
763 | 34 |
pair(writer, "remoteHost", _request.getRemoteHost());
|
764 | 34 |
pair(writer, "remoteUser", _request.getRemoteUser());
|
765 |
|
|
766 | 34 |
String sessionId = _request.getRequestedSessionId(); |
767 |
|
|
768 | 34 |
if (sessionId != null) |
769 |
{ |
|
770 | 0 |
StringBuffer buffer = new StringBuffer(sessionId);
|
771 |
|
|
772 | 0 |
if (_request.isRequestedSessionIdFromCookie())
|
773 | 0 |
buffer.append(" (from cookie)");
|
774 |
|
|
775 | 0 |
if (_request.isRequestedSessionIdFromURL())
|
776 | 0 |
buffer.append(" (from URL)");
|
777 |
|
|
778 | 0 |
if (_request.isRequestedSessionIdValid())
|
779 | 0 |
buffer.append(" (valid)");
|
780 |
|
|
781 | 0 |
pair(writer, "requestedSessionId", buffer.toString());
|
782 |
} |
|
783 |
|
|
784 | 34 |
pair(writer, "requestURI", _request.getRequestURI());
|
785 | 34 |
pair(writer, "scheme", _request.getScheme());
|
786 | 34 |
pair(writer, "serverName", _request.getServerName());
|
787 | 34 |
pair(writer, "serverPort", _request.getServerPort());
|
788 | 34 |
pair(writer, "contextPath", _request.getContextPath());
|
789 | 34 |
pair(writer, "servletPath", _request.getServletPath());
|
790 | 34 |
pair(writer, "userPrincipal", _request.getUserPrincipal());
|
791 |
|
|
792 |
// Now deal with any headers
|
|
793 |
|
|
794 | 34 |
List headers = getSorted(_request.getHeaderNames()); |
795 | 34 |
count = headers.size(); |
796 |
|
|
797 | 34 |
for (int i = 0; i < count; i++) |
798 |
{ |
|
799 | 0 |
if (i == 0)
|
800 |
{ |
|
801 | 0 |
section(writer, "Headers");
|
802 | 0 |
header(writer, "Name", "Value"); |
803 |
} |
|
804 |
|
|
805 | 0 |
String name = (String) headers.get(i); |
806 | 0 |
String value = _request.getHeader(name); |
807 |
|
|
808 | 0 |
pair(writer, name, value); |
809 |
} |
|
810 |
|
|
811 |
// Attributes
|
|
812 |
|
|
813 | 34 |
List attributes = getSorted(_request.getAttributeNames()); |
814 | 34 |
count = attributes.size(); |
815 |
|
|
816 | 34 |
for (int i = 0; i < count; i++) |
817 |
{ |
|
818 | 34 |
if (i == 0)
|
819 |
{ |
|
820 | 34 |
section(writer, "Attributes");
|
821 | 34 |
header(writer, "Name", "Value"); |
822 |
} |
|
823 |
|
|
824 | 34 |
String name = (String) attributes.get(i); |
825 |
|
|
826 | 34 |
pair(writer, name, _request.getAttribute(name)); |
827 |
} |
|
828 |
|
|
829 |
// Cookies ...
|
|
830 |
|
|
831 | 34 |
Cookie[] cookies = _request.getCookies(); |
832 |
|
|
833 | 34 |
if (cookies != null) |
834 |
{ |
|
835 | 34 |
for (int i = 0; i < cookies.length; i++) |
836 |
{ |
|
837 |
|
|
838 | 0 |
if (i == 0)
|
839 |
{ |
|
840 | 0 |
section(writer, "Cookies");
|
841 | 0 |
header(writer, "Name", "Value"); |
842 |
} |
|
843 |
|
|
844 | 0 |
Cookie cookie = cookies[i]; |
845 |
|
|
846 | 0 |
pair(writer, cookie.getName(), cookie.getValue()); |
847 |
|
|
848 |
} // Cookies loop
|
|
849 |
} |
|
850 |
|
|
851 | 34 |
writer.end(); // Request
|
852 |
|
|
853 | 34 |
object(writer, "Servlet");
|
854 | 34 |
writer.begin("table");
|
855 | 34 |
writer.attribute("class", "request-context-object"); |
856 |
|
|
857 | 34 |
section(writer, "Properties");
|
858 | 34 |
header(writer, "Name", "Value"); |
859 |
|
|
860 | 34 |
pair(writer, "servlet", _servlet);
|
861 | 34 |
pair(writer, "name", _servlet.getServletName());
|
862 | 34 |
pair(writer, "servletInfo", _servlet.getServletInfo());
|
863 |
|
|
864 | 34 |
ServletConfig config = _servlet.getServletConfig(); |
865 |
|
|
866 | 34 |
List names = getSorted(config.getInitParameterNames()); |
867 | 34 |
count = names.size(); |
868 |
|
|
869 | 34 |
for (int i = 0; i < count; i++) |
870 |
{ |
|
871 |
|
|
872 | 13 |
if (i == 0)
|
873 |
{ |
|
874 | 12 |
section(writer, "Init Parameters");
|
875 | 12 |
header(writer, "Name", "Value"); |
876 |
} |
|
877 |
|
|
878 | 13 |
String name = (String) names.get(i); |
879 |
; |
|
880 | 13 |
pair(writer, name, config.getInitParameter(name)); |
881 |
|
|
882 |
} |
|
883 |
|
|
884 | 34 |
writer.end(); // Servlet
|
885 |
|
|
886 | 34 |
ServletContext context = config.getServletContext(); |
887 |
|
|
888 | 34 |
object(writer, "Servlet Context");
|
889 | 34 |
writer.begin("table");
|
890 | 34 |
writer.attribute("class", "request-context-object"); |
891 |
|
|
892 | 34 |
section(writer, "Properties");
|
893 | 34 |
header(writer, "Name", "Value"); |
894 |
|
|
895 | 34 |
pair(writer, "majorVersion", context.getMajorVersion());
|
896 | 34 |
pair(writer, "minorVersion", context.getMinorVersion());
|
897 | 34 |
pair(writer, "serverInfo", context.getServerInfo());
|
898 |
|
|
899 | 34 |
names = getSorted(context.getInitParameterNames()); |
900 | 34 |
count = names.size(); |
901 | 34 |
for (int i = 0; i < count; i++) |
902 |
{ |
|
903 | 0 |
if (i == 0)
|
904 |
{ |
|
905 | 0 |
section(writer, "Initial Parameters");
|
906 | 0 |
header(writer, "Name", "Value"); |
907 |
} |
|
908 |
|
|
909 | 0 |
String name = (String) names.get(i); |
910 | 0 |
pair(writer, name, context.getInitParameter(name)); |
911 |
} |
|
912 |
|
|
913 | 34 |
names = getSorted(context.getAttributeNames()); |
914 | 34 |
count = names.size(); |
915 | 34 |
for (int i = 0; i < count; i++) |
916 |
{ |
|
917 | 0 |
if (i == 0)
|
918 |
{ |
|
919 | 0 |
section(writer, "Attributes");
|
920 | 0 |
header(writer, "Name", "Value"); |
921 |
} |
|
922 |
|
|
923 | 0 |
String name = (String) names.get(i); |
924 | 0 |
pair(writer, name, context.getAttribute(name)); |
925 |
} |
|
926 |
|
|
927 | 34 |
writer.end(); // Servlet Context
|
928 |
|
|
929 | 34 |
writeSystemProperties(writer); |
930 |
|
|
931 | 34 |
writer.end("table"); // The enclosing border |
932 |
} |
|
933 |
|
|
934 | 34 |
private void writeSystemProperties(IMarkupWriter writer) |
935 |
{ |
|
936 | 34 |
Properties properties = null;
|
937 |
|
|
938 | 34 |
object(writer, "JVM System Properties");
|
939 |
|
|
940 | 34 |
try
|
941 |
{ |
|
942 | 34 |
properties = System.getProperties(); |
943 |
} |
|
944 |
catch (SecurityException se)
|
|
945 |
{ |
|
946 | 0 |
writer.print("<p>");
|
947 | 0 |
writer.print(se.toString()); |
948 | 0 |
return;
|
949 |
} |
|
950 |
|
|
951 | 34 |
String pathSeparator = System.getProperty("path.separator", ";"); |
952 |
|
|
953 | 34 |
writer.begin("table");
|
954 | 34 |
writer.attribute("class", "request-context-object"); |
955 |
|
|
956 | 34 |
List names = new ArrayList(properties.keySet());
|
957 | 34 |
Collections.sort(names); |
958 | 34 |
int count = names.size();
|
959 |
|
|
960 | 34 |
for (int i = 0; i < count; i++) |
961 |
{ |
|
962 |
|
|
963 | 1768 |
if (i == 0)
|
964 | 34 |
header(writer, "Name", "Value"); |
965 |
|
|
966 | 1768 |
String name = (String) names.get(i); |
967 |
|
|
968 | 1768 |
String property = properties.getProperty(name); |
969 |
|
|
970 | 1768 |
if (property != null && property.indexOf(pathSeparator) > 0 && name.endsWith(".path")) |
971 |
{ |
|
972 | 102 |
writer.begin("tr");
|
973 | 102 |
writer.attribute("class", getRowClass());
|
974 |
|
|
975 | 102 |
writer.begin("th");
|
976 | 102 |
writer.print(name); |
977 | 102 |
writer.end(); |
978 |
|
|
979 | 102 |
writer.begin("td");
|
980 | 102 |
writer.begin("ul");
|
981 |
|
|
982 | 102 |
StringTokenizer tokenizer = new StringTokenizer(property, pathSeparator);
|
983 |
|
|
984 | 102 |
while (tokenizer.hasMoreTokens())
|
985 |
{ |
|
986 | 1802 |
writer.beginEmpty("li");
|
987 | 1802 |
writer.print(tokenizer.nextToken()); |
988 |
} |
|
989 |
|
|
990 | 102 |
writer.end("tr");
|
991 |
} |
|
992 |
else
|
|
993 |
{ |
|
994 | 1666 |
pair(writer, name, property); |
995 |
} |
|
996 |
} |
|
997 |
|
|
998 | 34 |
writer.end(); // System Properties
|
999 |
} |
|
1000 |
|
|
1001 |
/**
|
|
1002 |
* Invokes {@link #write(IMarkupWriter)}, which is used for debugging. Does nothing if the
|
|
1003 |
* cycle is rewinding.
|
|
1004 |
*/
|
|
1005 |
|
|
1006 | 34 |
public void render(IMarkupWriter writer, IRequestCycle cycle) |
1007 |
{ |
|
1008 | 34 |
if (!cycle.isRewinding())
|
1009 | 34 |
write(writer); |
1010 |
} |
|
1011 |
|
|
1012 |
/**
|
|
1013 |
* Returns the multipart decoder and lazily decodes the request parameters. This allows both for
|
|
1014 |
* this operation to be performed only when really needed and for opening the request for
|
|
1015 |
* reading much later, so that the Engine can have a chance to set the encoding that the request
|
|
1016 |
* needs to use.
|
|
1017 |
*
|
|
1018 |
* @return the multipart decoder or null if not needed for this request
|
|
1019 |
* @since 3.0
|
|
1020 |
*/
|
|
1021 | 826 |
private IMultipartDecoder getDecoder()
|
1022 |
{ |
|
1023 | 826 |
if (_decoder != null && !_decoded) |
1024 |
{ |
|
1025 | 6 |
_decoder.decode(_request); |
1026 | 6 |
_decoded = true;
|
1027 |
} |
|
1028 |
|
|
1029 | 826 |
return _decoder;
|
1030 |
} |
|
1031 |
|
|
1032 |
/**
|
|
1033 |
* Sets the multipart decoder to be used for the request.
|
|
1034 |
*
|
|
1035 |
* @param decoder
|
|
1036 |
* the multipart decoder
|
|
1037 |
* @since 3.0
|
|
1038 |
*/
|
|
1039 | 6 |
public void setDecoder(IMultipartDecoder decoder) |
1040 |
{ |
|
1041 | 6 |
_decoder = decoder; |
1042 | 6 |
_decoded = false;
|
1043 |
} |
|
1044 |
|
|
1045 |
/**
|
|
1046 |
* @since 3.1 --- but probably pretty temporary!
|
|
1047 |
*/
|
|
1048 | 0 |
public IApplicationSpecification getApplicationSpecification()
|
1049 |
{ |
|
1050 | 0 |
return _specification;
|
1051 |
} |
|
1052 |
|
|
1053 |
/**
|
|
1054 |
* Returns the context path, which is the portion of the URL that identifies the web application
|
|
1055 |
* context. This value may be blank (but not null) and does not end in a slash.
|
|
1056 |
*
|
|
1057 |
* @since 3.1
|
|
1058 |
*/
|
|
1059 | 172 |
public String getContextPath()
|
1060 |
{ |
|
1061 | 172 |
return _request.getContextPath();
|
1062 |
} |
|
1063 |
|
|
1064 |
} |
|