View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.access.spi;
15  
16  import java.io.Serializable;
17  import java.util.ArrayList;
18  import java.util.Enumeration;
19  import java.util.HashMap;
20  import java.util.List;
21  import java.util.Map;
22  import java.util.TreeMap;
23  import java.util.Vector;
24  
25  import javax.servlet.http.Cookie;
26  import javax.servlet.http.HttpServletRequest;
27  import javax.servlet.http.HttpServletResponse;
28  
29  import ch.qos.logback.access.AccessConstants;
30  import ch.qos.logback.access.pattern.AccessConverter;
31  import ch.qos.logback.access.servlet.Util;
32  import ch.qos.logback.core.spi.DeferredProcessingAware;
33  
34  // Contributors:  Joern Huxhorn (see also bug #110)
35  
36  /**
37   * The Access module's internal representation of logging events. When the
38   * logging component instance is called in the container to log then a
39   * <code>AccessEvent</code> instance is created. This instance is passed
40   * around to the different logback components.
41   * 
42   * @author Ceki G&uuml;lc&uuml;
43   * @author S&eacute;bastien Pennec
44   */
45  public class AccessEvent implements Serializable, DeferredProcessingAware {
46  
47    
48    private static final long serialVersionUID = 866718993618836343L;
49    
50    public final static String NA = "-";
51    public final static String[] NA_STRING_ARRAY = new String[] { AccessEvent.NA };
52  
53    public final static String EMPTY = "";
54    public static final int SENTINEL = -1;
55  
56    private transient final HttpServletRequest httpRequest;
57    private transient final HttpServletResponse httpResponse;
58  
59    String requestURI;
60    String requestURL;
61    String remoteHost;
62    String remoteUser;
63    String remoteAddr;
64    String protocol;
65    String method;
66    String serverName;
67    String requestContent;
68    String responseContent;
69  
70    Map<String, String> requestHeaderMap;
71    Map<String, String[]> requestParameterMap;
72    Map<String, String> responseHeaderMap;
73  
74    long contentLength = SENTINEL;
75    int statusCode = SENTINEL;
76    int localPort = SENTINEL;
77  
78    transient ServerAdapter serverAdapter;
79  
80    /**
81     * The number of milliseconds elapsed from 1/1/1970 until logging event was
82     * created.
83     */
84    private long timeStamp = 0;
85  
86    public AccessEvent(HttpServletRequest httpRequest,
87        HttpServletResponse httpResponse, ServerAdapter adapter) {
88      this.httpRequest = httpRequest;
89      this.httpResponse = httpResponse;
90      this.timeStamp = System.currentTimeMillis();
91      this.serverAdapter = adapter;
92    }
93  
94    /**
95     * Returns the underlying HttpServletRequest. After serialization the returned 
96     * value will be null. 
97     * 
98     * @return
99     */
100   public HttpServletRequest getRequest() {
101     return httpRequest;
102   }
103 
104   /**
105    * Returns the underlying HttpServletResponse. After serialization the returned 
106    * value will be null. 
107    * 
108    * @return
109    */
110   public HttpServletResponse getResponse() {
111     return httpResponse;
112   }
113 
114   public long getTimeStamp() {
115     return timeStamp;
116   }
117 
118   public void setTimeStamp(long timeStamp) {
119     if (this.timeStamp != 0) {
120       throw new IllegalStateException(
121           "timeStamp has been already set for this event.");
122     } else {
123       this.timeStamp = timeStamp;
124     }
125   }
126 
127   public String getRequestURI() {
128     if (requestURI == null) {
129       if (httpRequest != null) {
130         requestURI = httpRequest.getRequestURI();
131       } else {
132         requestURI = AccessEvent.NA;
133       }
134     }
135     return requestURI;
136   }
137 
138   /**
139    * The first line of the request.
140    */
141   public String getRequestURL() {
142     if (requestURL == null) {
143       if (httpRequest != null) {
144         StringBuffer buf = new StringBuffer();
145         buf.append(httpRequest.getMethod());
146         buf.append(AccessConverter.SPACE_CHAR);
147         buf.append(httpRequest.getRequestURI());
148         final String qStr = httpRequest.getQueryString();
149         if (qStr != null) {
150           buf.append(AccessConverter.QUESTION_CHAR);
151           buf.append(qStr);
152         }
153         buf.append(AccessConverter.SPACE_CHAR);
154         buf.append(httpRequest.getProtocol());
155         requestURL = buf.toString();
156       } else {
157         requestURL = AccessEvent.NA;
158       }
159     }
160     return requestURL;
161   }
162 
163   public String getRemoteHost() {
164     if (remoteHost == null) {
165       if (httpRequest != null) {
166         // the underlying implementation of HttpServletRequest will
167         // determine if remote lookup will be performed
168         remoteHost = httpRequest.getRemoteHost();
169       } else {
170         remoteHost = AccessEvent.NA;
171       }
172     }
173     return remoteHost;
174   }
175 
176   public String getRemoteUser() {
177     if (remoteUser == null) {
178       if (httpRequest != null) {
179         remoteUser = httpRequest.getRemoteUser();
180       } else {
181         remoteUser = AccessEvent.NA;
182       }
183     }
184     return remoteUser;
185   }
186 
187   public String getProtocol() {
188     if (protocol == null) {
189       if (httpRequest != null) {
190         protocol = httpRequest.getProtocol();
191       } else {
192         protocol = AccessEvent.NA;
193       }
194     }
195     return protocol;
196   }
197 
198   public String getMethod() {
199     if (method == null) {
200       if (httpRequest != null) {
201         method = httpRequest.getMethod();
202       } else {
203         method = AccessEvent.NA;
204       }
205     }
206     return method;
207   }
208 
209   public String getServerName() {
210     if (serverName == null) {
211       if (httpRequest != null) {
212         serverName = httpRequest.getServerName();
213       } else {
214         serverName = AccessEvent.NA;
215       }
216     }
217     return serverName;
218   }
219 
220   public String getRemoteAddr() {
221     if (remoteAddr == null) {
222       if (httpRequest != null) {
223         remoteAddr = httpRequest.getRemoteAddr();
224       } else {
225         remoteAddr = AccessEvent.NA;
226       }
227     }
228     return remoteAddr;
229   }
230 
231   public String getRequestHeader(String key) {
232     String result = null;
233     key = key.toLowerCase();
234     if (requestHeaderMap == null) {
235       if (httpRequest != null) {
236         buildRequestHeaderMap();
237         result = requestHeaderMap.get(key);
238       }
239     } else {
240       result = requestHeaderMap.get(key);
241     }
242 
243     if (result != null) {
244       return result;
245     } else {
246       return AccessEvent.NA;
247     }
248   }
249 
250   public Enumeration getRequestHeaderNames() {
251     // post-serialization
252     if (httpRequest == null) {
253       Vector<String> list = new Vector<String>(getRequestHeaderMap().keySet());
254       return list.elements();
255     }
256     return httpRequest.getHeaderNames();
257   }
258 
259   public Map<String, String> getRequestHeaderMap() {
260     if (requestHeaderMap == null) {
261       buildRequestHeaderMap();
262     }
263     return requestHeaderMap;
264   }
265 
266   public void buildRequestHeaderMap() {
267     // according to RFC 2616 header names are case insensitive
268     // latest versions of Tomcat return header names in lower-case
269     requestHeaderMap = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
270     Enumeration e = httpRequest.getHeaderNames();
271     if (e == null) {
272       return;
273     }
274     while (e.hasMoreElements()) {
275       String key = (String) e.nextElement();
276       requestHeaderMap.put(key, httpRequest.getHeader(key));
277     }
278   }
279 
280   public void buildRequestParameterMap() {
281     requestParameterMap = new HashMap<String, String[]>();
282     Enumeration e = httpRequest.getParameterNames();
283     if (e == null) {
284       return;
285     }
286     while (e.hasMoreElements()) {
287       String key = (String) e.nextElement();
288       requestParameterMap.put(key, httpRequest.getParameterValues(key));
289     }
290   }
291 
292   public Map<String, String[]> getRequestParameterMap() {
293     if (requestParameterMap == null) {
294       buildRequestParameterMap();
295     }
296     return requestParameterMap;
297   }
298 
299   /**
300    * Attributes are not serialized
301    * 
302    * @param key
303    */
304   public String getAttribute(String key) {
305     if (httpRequest != null) {
306       Object value = httpRequest.getAttribute(key);
307       if (value == null) {
308         return AccessEvent.NA;
309       } else {
310         return value.toString();
311       }
312     } else {
313       return AccessEvent.NA;
314     }
315   }
316 
317   public String[] getRequestParameter(String key) {
318     if (httpRequest != null) {
319       String[] value = httpRequest.getParameterValues(key);
320       if (value == null) {
321         return NA_STRING_ARRAY;
322       } else {
323         return value;
324       }
325     } else {
326       return NA_STRING_ARRAY;
327     }
328   }
329 
330   public String getCookie(String key) {
331 
332     if (httpRequest != null) {
333       Cookie[] cookieArray = httpRequest.getCookies();
334       if (cookieArray == null) {
335         return AccessEvent.NA;
336       }
337 
338       for (Cookie cookie : cookieArray) {
339         if (key.equals(cookie.getName())) {
340           return cookie.getValue();
341         }
342       }
343     }
344     return AccessEvent.NA;
345   }
346 
347   public long getContentLength() {
348     if (contentLength == SENTINEL) {
349       if (httpResponse != null) {
350         contentLength = serverAdapter.getContentLength();
351         return contentLength;
352       }
353     }
354     return contentLength;
355   }
356 
357   public int getStatusCode() {
358     if (statusCode == SENTINEL) {
359       if (httpResponse != null) {
360         statusCode = serverAdapter.getStatusCode();
361       }
362     }
363     return statusCode;
364   }
365 
366   public String getRequestContent() {
367     if (requestContent != null) {
368       return requestContent;
369     }
370 
371     if (Util.isFormUrlEncoded(httpRequest)) {
372       StringBuffer buf = new StringBuffer();
373 
374       Enumeration pramEnumeration = httpRequest.getParameterNames();
375 
376       // example: id=1234&user=cgu
377       // number=1233&x=1
378       int count = 0;
379       try {
380         while (pramEnumeration.hasMoreElements()) {
381 
382           String key = (String) pramEnumeration.nextElement();
383           if (count++ != 0) {
384             buf.append("&");
385           }
386           buf.append(key);
387           buf.append("=");
388           String val = httpRequest.getParameter(key);
389           if (val != null) {
390             buf.append(val);
391           } else {
392             buf.append("");
393           }
394         }
395       } catch (Exception e) {
396         // FIXME Why is try/catch required?
397         e.printStackTrace();
398       }
399       requestContent = buf.toString();
400     } else {
401 
402       // retreive the byte array placed by TeeFilter
403       byte[] inputBuffer = (byte[]) httpRequest
404           .getAttribute(AccessConstants.LB_INPUT_BUFFER);
405 
406       if (inputBuffer != null) {
407         requestContent = new String(inputBuffer);
408       }
409 
410       if (requestContent == null || requestContent.length() == 0) {
411         requestContent = EMPTY;
412       }
413     }
414 
415     return requestContent;
416   }
417 
418   public String getResponseContent() {
419     if (responseContent != null) {
420       return responseContent;
421     }
422 
423     if (Util.isImageResponse(httpResponse)) {
424       responseContent = "[IMAGE CONTENTS SUPPRESSED]";
425     } else {
426 
427       // retreive the byte array previously placed by TeeFilter
428       byte[] outputBuffer = (byte[]) httpRequest
429           .getAttribute(AccessConstants.LB_OUTPUT_BUFFER);
430 
431       if (outputBuffer != null) {
432         responseContent = new String(outputBuffer);
433       }
434       if (responseContent == null || responseContent.length() == 0) {
435         responseContent = EMPTY;
436       }
437     }
438 
439     return responseContent;
440   }
441 
442   public int getLocalPort() {
443     if (localPort == SENTINEL) {
444       if (httpRequest != null) {
445         localPort = httpRequest.getLocalPort();
446       }
447 
448     }
449     return localPort;
450   }
451 
452   public ServerAdapter getServerAdapter() {
453     return serverAdapter;
454   }
455 
456   public String getResponseHeader(String key) {
457     buildResponseHeaderMap();
458     return responseHeaderMap.get(key);
459   }
460 
461   void buildResponseHeaderMap() {
462     if (responseHeaderMap == null) {
463       responseHeaderMap = serverAdapter.buildResponseHeaderMap();
464     }
465   }
466 
467   public Map<String, String> getResponseHeaderMap() {
468     buildResponseHeaderMap();
469     return responseHeaderMap;
470   }
471 
472   public List<String> getResponseHeaderNameList() {
473     buildResponseHeaderMap();
474     return new ArrayList<String>(responseHeaderMap.keySet());
475   }
476 
477   public void prepareForDeferredProcessing() {
478     buildRequestHeaderMap();
479     buildRequestParameterMap();
480     buildResponseHeaderMap();
481     getLocalPort();
482     getMethod();
483     getProtocol();
484     getRemoteAddr();
485     getRemoteHost();
486     getRemoteUser();
487     getRequestURI();
488     getRequestURL();
489     getServerName();
490     getTimeStamp();
491 
492     getStatusCode();
493     getContentLength();
494     getRequestContent();
495     getResponseContent();
496   }
497 }