KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > valves > AccessLogValve


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.valves;
20
21
22 import java.io.File JavaDoc;
23 import java.io.FileWriter JavaDoc;
24 import java.io.IOException JavaDoc;
25 import java.io.PrintWriter JavaDoc;
26 import java.net.InetAddress JavaDoc;
27 import java.text.DecimalFormat JavaDoc;
28 import java.text.SimpleDateFormat JavaDoc;
29 import java.util.Calendar JavaDoc;
30 import java.util.Date JavaDoc;
31 import java.util.TimeZone JavaDoc;
32
33 import javax.servlet.ServletException JavaDoc;
34 import javax.servlet.http.Cookie JavaDoc;
35 import javax.servlet.http.HttpSession JavaDoc;
36
37 import org.apache.catalina.Lifecycle;
38 import org.apache.catalina.LifecycleException;
39 import org.apache.catalina.LifecycleListener;
40 import org.apache.catalina.connector.Request;
41 import org.apache.catalina.connector.Response;
42 import org.apache.catalina.util.LifecycleSupport;
43 import org.apache.catalina.util.StringManager;
44
45
46 /**
47  * <p>Implementation of the <b>Valve</b> interface that generates a web server
48  * access log with the detailed line contents matching a configurable pattern.
49  * The syntax of the available patterns is similar to that supported by the
50  * Apache <code>mod_log_config</code> module. As an additional feature,
51  * automatic rollover of log files when the date changes is also supported.</p>
52  *
53  * <p>Patterns for the logged message may include constant text or any of the
54  * following replacement strings, for which the corresponding information
55  * from the specified Response is substituted:</p>
56  * <ul>
57  * <li><b>%a</b> - Remote IP address
58  * <li><b>%A</b> - Local IP address
59  * <li><b>%b</b> - Bytes sent, excluding HTTP headers, or '-' if no bytes
60  * were sent
61  * <li><b>%B</b> - Bytes sent, excluding HTTP headers
62  * <li><b>%h</b> - Remote host name
63  * <li><b>%H</b> - Request protocol
64  * <li><b>%l</b> - Remote logical username from identd (always returns '-')
65  * <li><b>%m</b> - Request method
66  * <li><b>%p</b> - Local port
67  * <li><b>%q</b> - Query string (prepended with a '?' if it exists, otherwise
68  * an empty string
69  * <li><b>%r</b> - First line of the request
70  * <li><b>%s</b> - HTTP status code of the response
71  * <li><b>%S</b> - User session ID
72  * <li><b>%t</b> - Date and time, in Common Log Format format
73  * <li><b>%u</b> - Remote user that was authenticated
74  * <li><b>%U</b> - Requested URL path
75  * <li><b>%v</b> - Local server name
76  * <li><b>%D</b> - Time taken to process the request, in millis
77  * <li><b>%T</b> - Time taken to process the request, in seconds
78  * </ul>
79  * <p>In addition, the caller can specify one of the following aliases for
80  * commonly utilized patterns:</p>
81  * <ul>
82  * <li><b>common</b> - <code>%h %l %u %t "%r" %s %b</code>
83  * <li><b>combined</b> -
84  * <code>%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"</code>
85  * </ul>
86  *
87  * <p>
88  * There is also support to write information from the cookie, incoming
89  * header, the Session or something else in the ServletRequest.<br>
90  * It is modeled after the apache syntax:
91  * <ul>
92  * <li><code>%{xxx}i</code> for incoming headers
93  * <li><code>%{xxx}c</code> for a specific cookie
94  * <li><code>%{xxx}r</code> xxx is an attribute in the ServletRequest
95  * <li><code>%{xxx}s</code> xxx is an attribute in the HttpSession
96  * </ul>
97  * </p>
98  *
99  * <p>
100  * Conditional logging is also supported. This can be done with the
101  * <code>condition</code> property.
102  * If the value returned from ServletRequest.getAttribute(condition)
103  * yields a non-null value. The logging will be skipped.
104  * </p>
105  *
106  * @author Craig R. McClanahan
107  * @author Jason Brittain
108  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
109  */

110
111 public class AccessLogValve
112     extends ValveBase
113     implements Lifecycle {
114
115
116     // ----------------------------------------------------------- Constructors
117

118
119     /**
120      * Construct a new instance of this class with default property values.
121      */

122     public AccessLogValve() {
123
124         super();
125         setPattern("common");
126
127
128     }
129
130
131     // ----------------------------------------------------- Instance Variables
132

133
134     /**
135      * The as-of date for the currently open log file, or a zero-length
136      * string if there is no open log file.
137      */

138     private String JavaDoc dateStamp = "";
139
140
141     /**
142      * The directory in which log files are created.
143      */

144     private String JavaDoc directory = "logs";
145
146
147     /**
148      * The descriptive information about this implementation.
149      */

150     protected static final String JavaDoc info =
151         "org.apache.catalina.valves.AccessLogValve/1.0";
152
153
154     /**
155      * The lifecycle event support for this component.
156      */

157     protected LifecycleSupport lifecycle = new LifecycleSupport(this);
158
159
160     /**
161      * The set of month abbreviations for log messages.
162      */

163     protected static final String JavaDoc months[] =
164     { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
165       "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
166
167
168     /**
169      * If the current log pattern is the same as the common access log
170      * format pattern, then we'll set this variable to true and log in
171      * a more optimal and hard-coded way.
172      */

173     private boolean common = false;
174
175
176     /**
177      * For the combined format (common, plus useragent and referer), we do
178      * the same
179      */

180     private boolean combined = false;
181
182
183     /**
184      * The pattern used to format our access log lines.
185      */

186     private String JavaDoc pattern = null;
187
188
189     /**
190      * The prefix that is added to log file filenames.
191      */

192     private String JavaDoc prefix = "access_log.";
193
194
195     /**
196      * Should we rotate our log file? Default is true (like old behavior)
197      */

198     private boolean rotatable = true;
199
200
201     /**
202      * The string manager for this package.
203      */

204     private StringManager sm =
205         StringManager.getManager(Constants.Package);
206
207
208     /**
209      * Has this component been started yet?
210      */

211     private boolean started = false;
212
213
214     /**
215      * The suffix that is added to log file filenames.
216      */

217     private String JavaDoc suffix = "";
218
219
220     /**
221      * The PrintWriter to which we are currently logging, if any.
222      */

223     private PrintWriter JavaDoc writer = null;
224
225
226     /**
227      * A date formatter to format a Date into a date in the format
228      * "yyyy-MM-dd".
229      */

230     private SimpleDateFormat JavaDoc dateFormatter = null;
231
232
233     /**
234      * A date formatter to format Dates into a day string in the format
235      * "dd".
236      */

237     private SimpleDateFormat JavaDoc dayFormatter = null;
238
239
240     /**
241      * A date formatter to format a Date into a month string in the format
242      * "MM".
243      */

244     private SimpleDateFormat JavaDoc monthFormatter = null;
245
246
247     /**
248      * Time taken formatter for 3 decimal places.
249      */

250      private DecimalFormat JavaDoc timeTakenFormatter = null;
251
252
253     /**
254      * A date formatter to format a Date into a year string in the format
255      * "yyyy".
256      */

257     private SimpleDateFormat JavaDoc yearFormatter = null;
258
259
260     /**
261      * A date formatter to format a Date into a time in the format
262      * "kk:mm:ss" (kk is a 24-hour representation of the hour).
263      */

264     private SimpleDateFormat JavaDoc timeFormatter = null;
265
266
267     /**
268      * The system timezone.
269      */

270     private TimeZone JavaDoc timezone = null;
271
272     
273     /**
274      * The time zone offset relative to GMT in text form when daylight saving
275      * is not in operation.
276      */

277     private String JavaDoc timeZoneNoDST = null;
278
279
280     /**
281      * The time zone offset relative to GMT in text form when daylight saving
282      * is in operation.
283      */

284     private String JavaDoc timeZoneDST = null;
285     
286     
287     /**
288      * The system time when we last updated the Date that this valve
289      * uses for log lines.
290      */

291     private Date JavaDoc currentDate = null;
292
293
294     /**
295      * When formatting log lines, we often use strings like this one (" ").
296      */

297     private String JavaDoc space = " ";
298
299
300     /**
301      * Resolve hosts.
302      */

303     private boolean resolveHosts = false;
304
305
306     /**
307      * Instant when the log daily rotation was last checked.
308      */

309     private long rotationLastChecked = 0L;
310
311
312     /**
313      * Are we doing conditional logging. default false.
314      */

315     private String JavaDoc condition = null;
316
317
318     /**
319      * Date format to place in log file name. Use at your own risk!
320      */

321     private String JavaDoc fileDateFormat = null;
322
323     // ------------------------------------------------------------- Properties
324

325
326     /**
327      * Return the directory in which we create log files.
328      */

329     public String JavaDoc getDirectory() {
330
331         return (directory);
332
333     }
334
335
336     /**
337      * Set the directory in which we create log files.
338      *
339      * @param directory The new log file directory
340      */

341     public void setDirectory(String JavaDoc directory) {
342
343         this.directory = directory;
344
345     }
346
347
348     /**
349      * Return descriptive information about this implementation.
350      */

351     public String JavaDoc getInfo() {
352
353         return (info);
354
355     }
356
357
358     /**
359      * Return the format pattern.
360      */

361     public String JavaDoc getPattern() {
362
363         return (this.pattern);
364
365     }
366
367
368     /**
369      * Set the format pattern, first translating any recognized alias.
370      *
371      * @param pattern The new pattern
372      */

373     public void setPattern(String JavaDoc pattern) {
374
375         if (pattern == null)
376             pattern = "";
377         if (pattern.equals(Constants.AccessLog.COMMON_ALIAS))
378             pattern = Constants.AccessLog.COMMON_PATTERN;
379         if (pattern.equals(Constants.AccessLog.COMBINED_ALIAS))
380             pattern = Constants.AccessLog.COMBINED_PATTERN;
381         this.pattern = pattern;
382
383         if (this.pattern.equals(Constants.AccessLog.COMMON_PATTERN))
384             common = true;
385         else
386             common = false;
387
388         if (this.pattern.equals(Constants.AccessLog.COMBINED_PATTERN))
389             combined = true;
390         else
391             combined = false;
392
393     }
394
395
396     /**
397      * Return the log file prefix.
398      */

399     public String JavaDoc getPrefix() {
400
401         return (prefix);
402
403     }
404
405
406     /**
407      * Set the log file prefix.
408      *
409      * @param prefix The new log file prefix
410      */

411     public void setPrefix(String JavaDoc prefix) {
412
413         this.prefix = prefix;
414
415     }
416
417
418     /**
419      * Should we rotate the logs
420      */

421     public boolean isRotatable() {
422
423         return rotatable;
424
425     }
426
427
428     /**
429      * Set the value is we should we rotate the logs
430      *
431      * @param rotatable true is we should rotate.
432      */

433     public void setRotatable(boolean rotatable) {
434
435         this.rotatable = rotatable;
436
437     }
438
439
440     /**
441      * Return the log file suffix.
442      */

443     public String JavaDoc getSuffix() {
444
445         return (suffix);
446
447     }
448
449
450     /**
451      * Set the log file suffix.
452      *
453      * @param suffix The new log file suffix
454      */

455     public void setSuffix(String JavaDoc suffix) {
456
457         this.suffix = suffix;
458
459     }
460
461
462     /**
463      * Set the resolve hosts flag.
464      *
465      * @param resolveHosts The new resolve hosts value
466      */

467     public void setResolveHosts(boolean resolveHosts) {
468
469         this.resolveHosts = resolveHosts;
470
471     }
472
473
474     /**
475      * Get the value of the resolve hosts flag.
476      */

477     public boolean isResolveHosts() {
478
479         return resolveHosts;
480
481     }
482
483
484     /**
485      * Return whether the attribute name to look for when
486      * performing conditional loggging. If null, every
487      * request is logged.
488      */

489     public String JavaDoc getCondition() {
490
491         return condition;
492
493     }
494
495
496     /**
497      * Set the ServletRequest.attribute to look for to perform
498      * conditional logging. Set to null to log everything.
499      *
500      * @param condition Set to null to log everything
501      */

502     public void setCondition(String JavaDoc condition) {
503
504         this.condition = condition;
505
506     }
507
508     /**
509      * Return the date format date based log rotation.
510      */

511     public String JavaDoc getFileDateFormat() {
512         return fileDateFormat;
513     }
514
515
516     /**
517      * Set the date format date based log rotation.
518      */

519     public void setFileDateFormat(String JavaDoc fileDateFormat) {
520         this.fileDateFormat = fileDateFormat;
521     }
522
523     // --------------------------------------------------------- Public Methods
524

525
526     /**
527      * Log a message summarizing the specified request and response, according
528      * to the format specified by the <code>pattern</code> property.
529      *
530      * @param request Request being processed
531      * @param response Response being processed
532      *
533      * @exception IOException if an input/output error has occurred
534      * @exception ServletException if a servlet error has occurred
535      */

536     public void invoke(Request request, Response response)
537         throws IOException JavaDoc, ServletException JavaDoc {
538
539         // Pass this request on to the next valve in our pipeline
540
long t1=System.currentTimeMillis();
541
542         getNext().invoke(request, response);
543
544         long t2=System.currentTimeMillis();
545         long time=t2-t1;
546
547         if (condition!=null &&
548                 null!=request.getRequest().getAttribute(condition)) {
549             return;
550         }
551
552
553         Date JavaDoc date = getDate();
554         StringBuffer JavaDoc result = new StringBuffer JavaDoc();
555
556         // Check to see if we should log using the "common" access log pattern
557
if (common || combined) {
558             String JavaDoc value = null;
559
560             if (isResolveHosts())
561                 result.append(request.getRemoteHost());
562             else
563                 result.append(request.getRemoteAddr());
564
565             result.append(" - ");
566
567             value = request.getRemoteUser();
568             if (value == null)
569                 result.append("- ");
570             else {
571                 result.append(value);
572                 result.append(space);
573             }
574
575             result.append("[");
576             result.append(dayFormatter.format(date)); // Day
577
result.append('/');
578             result.append(lookup(monthFormatter.format(date))); // Month
579
result.append('/');
580             result.append(yearFormatter.format(date)); // Year
581
result.append(':');
582             result.append(timeFormatter.format(date)); // Time
583
result.append(space);
584             result.append(getTimeZone(date)); // Time Zone
585
result.append("] \"");
586
587             result.append(request.getMethod());
588             result.append(space);
589             result.append(request.getRequestURI());
590             if (request.getQueryString() != null) {
591                 result.append('?');
592                 result.append(request.getQueryString());
593             }
594             result.append(space);
595             result.append(request.getProtocol());
596             result.append("\" ");
597
598             result.append(response.getStatus());
599
600             result.append(space);
601
602             int length = response.getContentCount();
603
604             if (length <= 0)
605                 value = "-";
606             else
607                 value = "" + length;
608             result.append(value);
609
610             if (combined) {
611                 result.append(space);
612                 result.append("\"");
613                 String JavaDoc referer = request.getHeader("referer");
614                 if(referer != null)
615                     result.append(referer);
616                 else
617                     result.append("-");
618                 result.append("\"");
619
620                 result.append(space);
621                 result.append("\"");
622                 String JavaDoc ua = request.getHeader("user-agent");
623                 if(ua != null)
624                     result.append(ua);
625                 else
626                     result.append("-");
627                 result.append("\"");
628             }
629
630         } else {
631             // Generate a message based on the defined pattern
632
boolean replace = false;
633             for (int i = 0; i < pattern.length(); i++) {
634                 char ch = pattern.charAt(i);
635                 if (replace) {
636                     /* For code that processes {, the behavior will be ... if I
637                      * do not enounter a closing } - then I ignore the {
638                      */

639                     if ('{' == ch){
640                         StringBuffer JavaDoc name = new StringBuffer JavaDoc();
641                         int j = i + 1;
642                         for(;j < pattern.length() && '}' != pattern.charAt(j); j++) {
643                             name.append(pattern.charAt(j));
644                         }
645                         if (j+1 < pattern.length()) {
646                             /* the +1 was to account for } which we increment now */
647                             j++;
648                             result.append(replace(name.toString(),
649                                                 pattern.charAt(j),
650                                                 request,
651                                                 response));
652                             i=j; /*Since we walked more than one character*/
653                         } else {
654                             //D'oh - end of string - pretend we never did this
655
//and do processing the "old way"
656
result.append(replace(ch, date, request, response, time));
657                         }
658                     } else {
659                         result.append(replace(ch, date, request, response,time ));
660                     }
661                     replace = false;
662                 } else if (ch == '%') {
663                     replace = true;
664                 } else {
665                     result.append(ch);
666                 }
667             }
668         }
669         log(result.toString(), date);
670
671     }
672
673
674     // -------------------------------------------------------- Private Methods
675

676
677     /**
678      * Close the currently open log file (if any)
679      */

680     private synchronized void close() {
681
682         if (writer == null)
683             return;
684         writer.flush();
685         writer.close();
686         writer = null;
687         dateStamp = "";
688
689     }
690
691
692     /**
693      * Log the specified message to the log file, switching files if the date
694      * has changed since the previous log call.
695      *
696      * @param message Message to be logged
697      * @param date the current Date object (so this method doesn't need to
698      * create a new one)
699      */

700     public void log(String JavaDoc message, Date JavaDoc date) {
701
702         if (rotatable){
703             // Only do a logfile switch check once a second, max.
704
long systime = System.currentTimeMillis();
705             if ((systime - rotationLastChecked) > 1000) {
706
707                 // We need a new currentDate
708
currentDate = new Date JavaDoc(systime);
709                 rotationLastChecked = systime;
710
711                 // Check for a change of date
712
String JavaDoc tsDate = dateFormatter.format(currentDate);
713
714                 // If the date has changed, switch log files
715
if (!dateStamp.equals(tsDate)) {
716                     synchronized (this) {
717                         if (!dateStamp.equals(tsDate)) {
718                             close();
719                             dateStamp = tsDate;
720                             open();
721                         }
722                     }
723                 }
724
725             }
726         }
727
728         // Log this message
729
if (writer != null) {
730             writer.println(message);
731         }
732
733     }
734
735
736     /**
737      * Return the month abbreviation for the specified month, which must
738      * be a two-digit String.
739      *
740      * @param month Month number ("01" .. "12").
741      */

742     private String JavaDoc lookup(String JavaDoc month) {
743
744         int index;
745         try {
746             index = Integer.parseInt(month) - 1;
747         } catch (Throwable JavaDoc t) {
748             index = 0; // Can not happen, in theory
749
}
750         return (months[index]);
751
752     }
753
754
755     /**
756      * Open the new log file for the date specified by <code>dateStamp</code>.
757      */

758     private synchronized void open() {
759
760         // Create the directory if necessary
761
File JavaDoc dir = new File JavaDoc(directory);
762         if (!dir.isAbsolute())
763             dir = new File JavaDoc(System.getProperty("catalina.base"), directory);
764         dir.mkdirs();
765
766         // Open the current log file
767
try {
768             String JavaDoc pathname;
769             // If no rotate - no need for dateStamp in fileName
770
if (rotatable){
771                 pathname = dir.getAbsolutePath() + File.separator +
772                             prefix + dateStamp + suffix;
773             } else {
774                 pathname = dir.getAbsolutePath() + File.separator +
775                             prefix + suffix;
776             }
777             writer = new PrintWriter JavaDoc(new FileWriter JavaDoc(pathname, true), true);
778         } catch (IOException JavaDoc e) {
779             writer = null;
780         }
781
782     }
783
784
785     /**
786      * Return the replacement text for the specified pattern character.
787      *
788      * @param pattern Pattern character identifying the desired text
789      * @param date the current Date so that this method doesn't need to
790      * create one
791      * @param request Request being processed
792      * @param response Response being processed
793      */

794     private String JavaDoc replace(char pattern, Date JavaDoc date, Request request,
795                            Response response, long time) {
796
797         String JavaDoc value = null;
798
799         if (pattern == 'a') {
800             value = request.getRemoteAddr();
801         } else if (pattern == 'A') {
802             try {
803                 value = InetAddress.getLocalHost().getHostAddress();
804             } catch(Throwable JavaDoc e){
805                 value = "127.0.0.1";
806             }
807         } else if (pattern == 'b') {
808             int length = response.getContentCount();
809             if (length <= 0)
810                 value = "-";
811             else
812                 value = "" + length;
813         } else if (pattern == 'B') {
814             value = "" + response.getContentLength();
815         } else if (pattern == 'h') {
816             value = request.getRemoteHost();
817         } else if (pattern == 'H') {
818             value = request.getProtocol();
819         } else if (pattern == 'l') {
820             value = "-";
821         } else if (pattern == 'm') {
822             if (request != null)
823                 value = request.getMethod();
824             else
825                 value = "";
826         } else if (pattern == 'p') {
827             value = "" + request.getServerPort();
828         } else if (pattern == 'D') {
829                     value = "" + time;
830         } else if (pattern == 'q') {
831             String JavaDoc query = null;
832             if (request != null)
833                 query = request.getQueryString();
834             if (query != null)
835                 value = "?" + query;
836             else
837                 value = "";
838         } else if (pattern == 'r') {
839             StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
840             if (request != null) {
841                 sb.append(request.getMethod());
842                 sb.append(space);
843                 sb.append(request.getRequestURI());
844                 if (request.getQueryString() != null) {
845                     sb.append('?');
846                     sb.append(request.getQueryString());
847                 }
848                 sb.append(space);
849                 sb.append(request.getProtocol());
850             } else {
851                 sb.append("- - ");
852                 sb.append(request.getProtocol());
853             }
854             value = sb.toString();
855         } else if (pattern == 'S') {
856             if (request != null)
857                 if (request.getSession(false) != null)
858                     value = request.getSessionInternal(false).getIdInternal();
859                 else value = "-";
860             else
861                 value = "-";
862         } else if (pattern == 's') {
863             if (response != null)
864                 value = "" + response.getStatus();
865             else
866                 value = "-";
867         } else if (pattern == 't') {
868             StringBuffer JavaDoc temp = new StringBuffer JavaDoc("[");
869             temp.append(dayFormatter.format(date)); // Day
870
temp.append('/');
871             temp.append(lookup(monthFormatter.format(date))); // Month
872
temp.append('/');
873             temp.append(yearFormatter.format(date)); // Year
874
temp.append(':');
875             temp.append(timeFormatter.format(date)); // Time
876
temp.append(' ');
877             temp.append(getTimeZone(date)); // Timezone
878
temp.append(']');
879             value = temp.toString();
880         } else if (pattern == 'T') {
881             value = timeTakenFormatter.format(time/1000d);
882         } else if (pattern == 'u') {
883             if (request != null)
884                 value = request.getRemoteUser();
885             if (value == null)
886                 value = "-";
887         } else if (pattern == 'U') {
888             if (request != null)
889                 value = request.getRequestURI();
890             else
891                 value = "-";
892         } else if (pattern == 'v') {
893             value = request.getServerName();
894         } else {
895             value = "???" + pattern + "???";
896         }
897
898         if (value == null)
899             return ("");
900         else
901             return (value);
902
903     }
904
905
906     /**
907      * Return the replacement text for the specified "header/parameter".
908      *
909      * @param header The header/parameter to get
910      * @param type Where to get it from i=input,c=cookie,r=ServletRequest,s=Session
911      * @param request Request being processed
912      * @param response Response being processed
913      */

914     private String JavaDoc replace(String JavaDoc header, char type, Request request,
915                            Response response) {
916
917         Object JavaDoc value = null;
918
919         switch (type) {
920             case 'i':
921                 if (null != request)
922                     value = request.getHeader(header);
923                 else
924                     value= "??";
925                 break;
926 /*
927             // Someone please make me work
928             case 'o':
929                 break;
930 */

931             case 'c':
932                  Cookie JavaDoc[] c = request.getCookies();
933                  for (int i=0; c != null && i < c.length; i++){
934                      if (header.equals(c[i].getName())){
935                          value = c[i].getValue();
936                          break;
937                      }
938                  }
939                 break;
940             case 'r':
941                 if (null != request)
942                     value = request.getAttribute(header);
943                 else
944                     value= "??";
945                 break;
946             case 's':
947                 if (null != request) {
948                     HttpSession JavaDoc sess = request.getSession(false);
949                     if (null != sess)
950                         value = sess.getAttribute(header);
951                 }
952                break;
953             default:
954                 value = "???";
955         }
956
957         /* try catch in case toString() barfs */
958         try {
959             if (value!=null)
960                 if (value instanceof String JavaDoc)
961                     return (String JavaDoc)value;
962                 else
963                     return value.toString();
964             else
965                return "-";
966         } catch(Throwable JavaDoc e) {
967             return "-";
968         }
969     }
970
971
972     /**
973      * This method returns a Date object that is accurate to within one
974      * second. If a thread calls this method to get a Date and it's been
975      * less than 1 second since a new Date was created, this method
976      * simply gives out the same Date again so that the system doesn't
977      * spend time creating Date objects unnecessarily.
978      *
979      * @return Date
980      */

981     private Date JavaDoc getDate() {
982         if(currentDate == null) {
983         currentDate = new Date JavaDoc();
984         } else {
985           // Only create a new Date once per second, max.
986
long systime = System.currentTimeMillis();
987           if ((systime - currentDate.getTime()) > 1000) {
988               currentDate = new Date JavaDoc(systime);
989           }
990     }
991
992         return currentDate;
993     }
994
995
996     private String JavaDoc getTimeZone(Date JavaDoc date) {
997         if (timezone.inDaylightTime(date)) {
998             return timeZoneDST;
999         } else {
1000            return timeZoneNoDST;
1001        }
1002    }
1003    
1004    
1005    private String JavaDoc calculateTimeZoneOffset(long offset) {
1006        StringBuffer JavaDoc tz = new StringBuffer JavaDoc();
1007        if ((offset<0)) {
1008            tz.append("-");
1009            offset = -offset;
1010        } else {
1011            tz.append("+");
1012        }
1013
1014        long hourOffset = offset/(1000*60*60);
1015        long minuteOffset = (offset/(1000*60)) % 60;
1016
1017        if (hourOffset<10)
1018            tz.append("0");
1019        tz.append(hourOffset);
1020
1021        if (minuteOffset<10)
1022            tz.append("0");
1023        tz.append(minuteOffset);
1024
1025        return tz.toString();
1026    }
1027
1028
1029    // ------------------------------------------------------ Lifecycle Methods
1030

1031
1032    /**
1033     * Add a lifecycle event listener to this component.
1034     *
1035     * @param listener The listener to add
1036     */

1037    public void addLifecycleListener(LifecycleListener listener) {
1038
1039        lifecycle.addLifecycleListener(listener);
1040
1041    }
1042
1043
1044    /**
1045     * Get the lifecycle listeners associated with this lifecycle. If this
1046     * Lifecycle has no listeners registered, a zero-length array is returned.
1047     */

1048    public LifecycleListener[] findLifecycleListeners() {
1049
1050        return lifecycle.findLifecycleListeners();
1051
1052    }
1053
1054
1055    /**
1056     * Remove a lifecycle event listener from this component.
1057     *
1058     * @param listener The listener to add
1059     */

1060    public void removeLifecycleListener(LifecycleListener listener) {
1061
1062        lifecycle.removeLifecycleListener(listener);
1063
1064    }
1065
1066
1067    /**
1068     * Prepare for the beginning of active use of the public methods of this
1069     * component. This method should be called after <code>configure()</code>,
1070     * and before any of the public methods of the component are utilized.
1071     *
1072     * @exception LifecycleException if this component detects a fatal error
1073     * that prevents this component from being used
1074     */

1075    public void start() throws LifecycleException {
1076
1077        // Validate and update our current component state
1078
if (started)
1079            throw new LifecycleException
1080                (sm.getString("accessLogValve.alreadyStarted"));
1081        lifecycle.fireLifecycleEvent(START_EVENT, null);
1082        started = true;
1083
1084        // Initialize the timeZone, Date formatters, and currentDate
1085
timezone = TimeZone.getDefault();
1086        timeZoneNoDST = calculateTimeZoneOffset(timezone.getRawOffset());
1087        Calendar JavaDoc calendar = Calendar.getInstance(timezone);
1088        int offset = calendar.get(Calendar.DST_OFFSET);
1089        timeZoneDST = calculateTimeZoneOffset(timezone.getRawOffset()+offset);
1090        
1091        if (fileDateFormat==null || fileDateFormat.length()==0)
1092            fileDateFormat = "yyyy-MM-dd";
1093        dateFormatter = new SimpleDateFormat JavaDoc(fileDateFormat);
1094        dateFormatter.setTimeZone(timezone);
1095        dayFormatter = new SimpleDateFormat JavaDoc("dd");
1096        dayFormatter.setTimeZone(timezone);
1097        monthFormatter = new SimpleDateFormat JavaDoc("MM");
1098        monthFormatter.setTimeZone(timezone);
1099        yearFormatter = new SimpleDateFormat JavaDoc("yyyy");
1100        yearFormatter.setTimeZone(timezone);
1101        timeFormatter = new SimpleDateFormat JavaDoc("HH:mm:ss");
1102        timeFormatter.setTimeZone(timezone);
1103        currentDate = new Date JavaDoc();
1104        dateStamp = dateFormatter.format(currentDate);
1105        timeTakenFormatter = new DecimalFormat JavaDoc("0.000");
1106
1107        open();
1108
1109    }
1110
1111
1112    /**
1113     * Gracefully terminate the active use of the public methods of this
1114     * component. This method should be the last one called on a given
1115     * instance of this component.
1116     *
1117     * @exception LifecycleException if this component detects a fatal error
1118     * that needs to be reported
1119     */

1120    public void stop() throws LifecycleException {
1121
1122        // Validate and update our current component state
1123
if (!started)
1124            throw new LifecycleException
1125                (sm.getString("accessLogValve.notStarted"));
1126        lifecycle.fireLifecycleEvent(STOP_EVENT, null);
1127        started = false;
1128
1129        close();
1130
1131    }
1132}
1133
Popular Tags