View Javadoc

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