Source Code Cross Referenced for AccessLogValve.java in  » Sevlet-Container » apache-tomcat-6.0.14 » org » apache » catalina » valves » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Sevlet Container » apache tomcat 6.0.14 » org.apache.catalina.valves 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * Licensed to the Apache Software Foundation (ASF) under one or more
0003:         * contributor license agreements.  See the NOTICE file distributed with
0004:         * this work for additional information regarding copyright ownership.
0005:         * The ASF licenses this file to You under the Apache License, Version 2.0
0006:         * (the "License"); you may not use this file except in compliance with
0007:         * the License.  You may obtain a copy of the License at
0008:         *
0009:         *      http://www.apache.org/licenses/LICENSE-2.0
0010:         *
0011:         * Unless required by applicable law or agreed to in writing, software
0012:         * distributed under the License is distributed on an "AS IS" BASIS,
0013:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0014:         * See the License for the specific language governing permissions and
0015:         * limitations under the License.
0016:         */
0017:
0018:        package org.apache.catalina.valves;
0019:
0020:        import java.io.BufferedWriter;
0021:        import java.io.File;
0022:        import java.io.FileWriter;
0023:        import java.io.IOException;
0024:        import java.io.PrintWriter;
0025:        import java.net.InetAddress;
0026:        import java.text.SimpleDateFormat;
0027:        import java.util.ArrayList;
0028:        import java.util.Calendar;
0029:        import java.util.Date;
0030:        import java.util.List;
0031:        import java.util.TimeZone;
0032:
0033:        import javax.servlet.ServletException;
0034:        import javax.servlet.http.Cookie;
0035:        import javax.servlet.http.HttpSession;
0036:
0037:        import org.apache.catalina.Lifecycle;
0038:        import org.apache.catalina.LifecycleException;
0039:        import org.apache.catalina.LifecycleListener;
0040:        import org.apache.catalina.connector.Request;
0041:        import org.apache.catalina.connector.Response;
0042:        import org.apache.catalina.util.LifecycleSupport;
0043:        import org.apache.catalina.util.StringManager;
0044:        import org.apache.juli.logging.Log;
0045:        import org.apache.juli.logging.LogFactory;
0046:
0047:        /**
0048:         * <p>Implementation of the <b>Valve</b> interface that generates a web server
0049:         * access log with the detailed line contents matching a configurable pattern.
0050:         * The syntax of the available patterns is similar to that supported by the
0051:         * Apache <code>mod_log_config</code> module.  As an additional feature,
0052:         * automatic rollover of log files when the date changes is also supported.</p>
0053:         *
0054:         * <p>Patterns for the logged message may include constant text or any of the
0055:         * following replacement strings, for which the corresponding information
0056:         * from the specified Response is substituted:</p>
0057:         * <ul>
0058:         * <li><b>%a</b> - Remote IP address
0059:         * <li><b>%A</b> - Local IP address
0060:         * <li><b>%b</b> - Bytes sent, excluding HTTP headers, or '-' if no bytes
0061:         *     were sent
0062:         * <li><b>%B</b> - Bytes sent, excluding HTTP headers
0063:         * <li><b>%h</b> - Remote host name
0064:         * <li><b>%H</b> - Request protocol
0065:         * <li><b>%l</b> - Remote logical username from identd (always returns '-')
0066:         * <li><b>%m</b> - Request method
0067:         * <li><b>%p</b> - Local port
0068:         * <li><b>%q</b> - Query string (prepended with a '?' if it exists, otherwise
0069:         *     an empty string
0070:         * <li><b>%r</b> - First line of the request
0071:         * <li><b>%s</b> - HTTP status code of the response
0072:         * <li><b>%S</b> - User session ID
0073:         * <li><b>%t</b> - Date and time, in Common Log Format format
0074:         * <li><b>%u</b> - Remote user that was authenticated
0075:         * <li><b>%U</b> - Requested URL path
0076:         * <li><b>%v</b> - Local server name
0077:         * <li><b>%D</b> - Time taken to process the request, in millis
0078:         * <li><b>%T</b> - Time taken to process the request, in seconds
0079:         * </ul>
0080:         * <p>In addition, the caller can specify one of the following aliases for
0081:         * commonly utilized patterns:</p>
0082:         * <ul>
0083:         * <li><b>common</b> - <code>%h %l %u %t "%r" %s %b</code>
0084:         * <li><b>combined</b> -
0085:         *   <code>%h %l %u %t "%r" %s %b "%{Referer}i" "%{User-Agent}i"</code>
0086:         * </ul>
0087:         *
0088:         * <p>
0089:         * There is also support to write information from the cookie, incoming
0090:         * header, the Session or something else in the ServletRequest.<br>
0091:         * It is modeled after the apache syntax:
0092:         * <ul>
0093:         * <li><code>%{xxx}i</code> for incoming headers
0094:         * <li><code>%{xxx}c</code> for a specific cookie
0095:         * <li><code>%{xxx}r</code> xxx is an attribute in the ServletRequest
0096:         * <li><code>%{xxx}s</code> xxx is an attribute in the HttpSession
0097:         * </ul>
0098:         * </p>
0099:         *
0100:         * <p>
0101:         * Conditional logging is also supported. This can be done with the
0102:         * <code>condition</code> property.
0103:         * If the value returned from ServletRequest.getAttribute(condition)
0104:         * yields a non-null value. The logging will be skipped.
0105:         * </p>
0106:         *
0107:         * @author Craig R. McClanahan
0108:         * @author Jason Brittain
0109:         * @author Remy Maucherat
0110:         * @author Takayuki Kaneko
0111:         * @version $Revision: 539787 $ $Date: 2007-01-04 12:17:11 +0900
0112:         */
0113:
0114:        public class AccessLogValve extends ValveBase implements  Lifecycle {
0115:
0116:            private static Log log = LogFactory.getLog(AccessLogValve.class);
0117:
0118:            // ----------------------------------------------------- Instance Variables
0119:
0120:            /**
0121:             * The as-of date for the currently open log file, or a zero-length
0122:             * string if there is no open log file.
0123:             */
0124:            private String dateStamp = "";
0125:
0126:            /**
0127:             * The directory in which log files are created.
0128:             */
0129:            private String directory = "logs";
0130:
0131:            /**
0132:             * The descriptive information about this implementation.
0133:             */
0134:            protected static final String info = "org.apache.catalina.valves.AccessLogValve/2.0";
0135:
0136:            /**
0137:             * The lifecycle event support for this component.
0138:             */
0139:            protected LifecycleSupport lifecycle = new LifecycleSupport(this );
0140:
0141:            /**
0142:             * The set of month abbreviations for log messages.
0143:             */
0144:            protected static final String months[] = { "Jan", "Feb", "Mar",
0145:                    "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
0146:                    "Dec" };
0147:
0148:            /**
0149:             * enabled this component
0150:             */
0151:            protected boolean enabled = true;
0152:
0153:            /**
0154:             * The pattern used to format our access log lines.
0155:             */
0156:            protected String pattern = null;
0157:
0158:            /**
0159:             * The prefix that is added to log file filenames.
0160:             */
0161:            protected String prefix = "access_log.";
0162:
0163:            /**
0164:             * Should we rotate our log file? Default is true (like old behavior)
0165:             */
0166:            protected boolean rotatable = true;
0167:
0168:            /**
0169:             * Buffered logging.
0170:             */
0171:            private boolean buffered = true;
0172:
0173:            /**
0174:             * The string manager for this package.
0175:             */
0176:            protected StringManager sm = StringManager
0177:                    .getManager(Constants.Package);
0178:
0179:            /**
0180:             * Has this component been started yet?
0181:             */
0182:            protected boolean started = false;
0183:
0184:            /**
0185:             * The suffix that is added to log file filenames.
0186:             */
0187:            protected String suffix = "";
0188:
0189:            /**
0190:             * The PrintWriter to which we are currently logging, if any.
0191:             */
0192:            protected PrintWriter writer = null;
0193:
0194:            /**
0195:             * A date formatter to format a Date into a date in the format
0196:             * "yyyy-MM-dd".
0197:             */
0198:            protected SimpleDateFormat fileDateFormatter = null;
0199:
0200:            /**
0201:             * A date formatter to format Dates into a day string in the format
0202:             * "dd".
0203:             */
0204:            private SimpleDateFormat dayFormatter = null;
0205:
0206:            /**
0207:             * A date formatter to format a Date into a month string in the format
0208:             * "MM".
0209:             */
0210:            private SimpleDateFormat monthFormatter = null;
0211:
0212:            /**
0213:             * A date formatter to format a Date into a year string in the format
0214:             * "yyyy".
0215:             */
0216:            private SimpleDateFormat yearFormatter = null;
0217:
0218:            /**
0219:             * A date formatter to format a Date into a time in the format
0220:             * "kk:mm:ss" (kk is a 24-hour representation of the hour).
0221:             */
0222:            private SimpleDateFormat timeFormatter = null;
0223:
0224:            /**
0225:             * The system timezone.
0226:             */
0227:            private TimeZone timezone = null;
0228:
0229:            /**
0230:             * The time zone offset relative to GMT in text form when daylight saving
0231:             * is not in operation.
0232:             */
0233:            private String timeZoneNoDST = null;
0234:
0235:            /**
0236:             * The time zone offset relative to GMT in text form when daylight saving
0237:             * is in operation.
0238:             */
0239:            private String timeZoneDST = null;
0240:
0241:            /**
0242:             * The current log file we are writing to. Helpful when checkExists
0243:             * is true.
0244:             */
0245:            protected File currentLogFile = null;
0246:
0247:            /**
0248:             * The system time when we last updated the Date that this valve
0249:             * uses for log lines.
0250:             */
0251:            private Date currentDate = null;
0252:
0253:            private long currentMillis = 0;
0254:
0255:            /**
0256:             * Resolve hosts.
0257:             */
0258:            private boolean resolveHosts = false;
0259:
0260:            /**
0261:             * Instant when the log daily rotation was last checked.
0262:             */
0263:            private long rotationLastChecked = 0L;
0264:
0265:            /**
0266:             * Do we check for log file existence? Helpful if an external
0267:             * agent renames the log file so we can automagically recreate it.
0268:             */
0269:            private boolean checkExists = false;
0270:
0271:            /**
0272:             * Are we doing conditional logging. default false.
0273:             */
0274:            protected String condition = null;
0275:
0276:            /**
0277:             * Date format to place in log file name. Use at your own risk!
0278:             */
0279:            protected String fileDateFormat = null;
0280:
0281:            /**
0282:             * Array of AccessLogElement, they will be used to make log message.
0283:             */
0284:            protected AccessLogElement[] logElements = null;
0285:
0286:            // ------------------------------------------------------------- Properties
0287:
0288:            /**
0289:             * @return Returns the enabled.
0290:             */
0291:            public boolean getEnabled() {
0292:                return enabled;
0293:            }
0294:
0295:            /**
0296:             * @param enabled
0297:             *            The enabled to set.
0298:             */
0299:            public void setEnabled(boolean enabled) {
0300:                this .enabled = enabled;
0301:            }
0302:
0303:            /**
0304:             * Return the directory in which we create log files.
0305:             */
0306:            public String getDirectory() {
0307:                return (directory);
0308:            }
0309:
0310:            /**
0311:             * Set the directory in which we create log files.
0312:             *
0313:             * @param directory The new log file directory
0314:             */
0315:            public void setDirectory(String directory) {
0316:                this .directory = directory;
0317:            }
0318:
0319:            /**
0320:             * Return descriptive information about this implementation.
0321:             */
0322:            public String getInfo() {
0323:                return (info);
0324:            }
0325:
0326:            /**
0327:             * Return the format pattern.
0328:             */
0329:            public String getPattern() {
0330:                return (this .pattern);
0331:            }
0332:
0333:            /**
0334:             * Set the format pattern, first translating any recognized alias.
0335:             *
0336:             * @param pattern The new pattern
0337:             */
0338:            public void setPattern(String pattern) {
0339:                if (pattern == null)
0340:                    pattern = "";
0341:                if (pattern.equals(Constants.AccessLog.COMMON_ALIAS))
0342:                    pattern = Constants.AccessLog.COMMON_PATTERN;
0343:                if (pattern.equals(Constants.AccessLog.COMBINED_ALIAS))
0344:                    pattern = Constants.AccessLog.COMBINED_PATTERN;
0345:                this .pattern = pattern;
0346:                logElements = createLogElements();
0347:            }
0348:
0349:            /**
0350:             * Check for file existence before logging.
0351:             */
0352:            public boolean isCheckExists() {
0353:
0354:                return checkExists;
0355:
0356:            }
0357:
0358:            /**
0359:             * Set whether to check for log file existence before logging.
0360:             *
0361:             * @param checkExists true meaning to check for file existence.
0362:             */
0363:            public void setCheckExists(boolean checkExists) {
0364:
0365:                this .checkExists = checkExists;
0366:
0367:            }
0368:
0369:            /**
0370:             * Return the log file prefix.
0371:             */
0372:            public String getPrefix() {
0373:                return (prefix);
0374:            }
0375:
0376:            /**
0377:             * Set the log file prefix.
0378:             *
0379:             * @param prefix The new log file prefix
0380:             */
0381:            public void setPrefix(String prefix) {
0382:                this .prefix = prefix;
0383:            }
0384:
0385:            /**
0386:             * Should we rotate the logs
0387:             */
0388:            public boolean isRotatable() {
0389:                return rotatable;
0390:            }
0391:
0392:            /**
0393:             * Set the value is we should we rotate the logs
0394:             *
0395:             * @param rotatable true is we should rotate.
0396:             */
0397:            public void setRotatable(boolean rotatable) {
0398:                this .rotatable = rotatable;
0399:            }
0400:
0401:            /**
0402:             * Is the logging buffered
0403:             */
0404:            public boolean isBuffered() {
0405:                return buffered;
0406:            }
0407:
0408:            /**
0409:             * Set the value if the logging should be buffered
0410:             *
0411:             * @param buffered true if buffered.
0412:             */
0413:            public void setBuffered(boolean buffered) {
0414:                this .buffered = buffered;
0415:            }
0416:
0417:            /**
0418:             * Return the log file suffix.
0419:             */
0420:            public String getSuffix() {
0421:                return (suffix);
0422:            }
0423:
0424:            /**
0425:             * Set the log file suffix.
0426:             *
0427:             * @param suffix The new log file suffix
0428:             */
0429:            public void setSuffix(String suffix) {
0430:                this .suffix = suffix;
0431:            }
0432:
0433:            /**
0434:             * Set the resolve hosts flag.
0435:             *
0436:             * @param resolveHosts The new resolve hosts value
0437:             */
0438:            public void setResolveHosts(boolean resolveHosts) {
0439:                this .resolveHosts = resolveHosts;
0440:            }
0441:
0442:            /**
0443:             * Get the value of the resolve hosts flag.
0444:             */
0445:            public boolean isResolveHosts() {
0446:                return resolveHosts;
0447:            }
0448:
0449:            /**
0450:             * Return whether the attribute name to look for when
0451:             * performing conditional loggging. If null, every
0452:             * request is logged.
0453:             */
0454:            public String getCondition() {
0455:                return condition;
0456:            }
0457:
0458:            /**
0459:             * Set the ServletRequest.attribute to look for to perform
0460:             * conditional logging. Set to null to log everything.
0461:             *
0462:             * @param condition Set to null to log everything
0463:             */
0464:            public void setCondition(String condition) {
0465:                this .condition = condition;
0466:            }
0467:
0468:            /**
0469:             *  Return the date format date based log rotation.
0470:             */
0471:            public String getFileDateFormat() {
0472:                return fileDateFormat;
0473:            }
0474:
0475:            /**
0476:             *  Set the date format date based log rotation.
0477:             */
0478:            public void setFileDateFormat(String fileDateFormat) {
0479:                this .fileDateFormat = fileDateFormat;
0480:            }
0481:
0482:            // --------------------------------------------------------- Public Methods
0483:
0484:            /**
0485:             * Execute a periodic task, such as reloading, etc. This method will be
0486:             * invoked inside the classloading context of this container. Unexpected
0487:             * throwables will be caught and logged.
0488:             */
0489:            public void backgroundProcess() {
0490:                if (started && getEnabled() && writer != null && buffered) {
0491:                    writer.flush();
0492:                }
0493:            }
0494:
0495:            /**
0496:             * Log a message summarizing the specified request and response, according
0497:             * to the format specified by the <code>pattern</code> property.
0498:             *
0499:             * @param request Request being processed
0500:             * @param response Response being processed
0501:             *
0502:             * @exception IOException if an input/output error has occurred
0503:             * @exception ServletException if a servlet error has occurred
0504:             */
0505:            public void invoke(Request request, Response response)
0506:                    throws IOException, ServletException {
0507:
0508:                if (started && getEnabled()) {
0509:                    // Pass this request on to the next valve in our pipeline
0510:                    long t1 = System.currentTimeMillis();
0511:
0512:                    getNext().invoke(request, response);
0513:
0514:                    long t2 = System.currentTimeMillis();
0515:                    long time = t2 - t1;
0516:
0517:                    if (logElements == null
0518:                            || condition != null
0519:                            && null != request.getRequest().getAttribute(
0520:                                    condition)) {
0521:                        return;
0522:                    }
0523:
0524:                    Date date = getDate();
0525:                    StringBuffer result = new StringBuffer();
0526:
0527:                    for (int i = 0; i < logElements.length; i++) {
0528:                        logElements[i].addElement(result, date, request,
0529:                                response, time);
0530:                    }
0531:
0532:                    log(result.toString());
0533:                } else
0534:                    getNext().invoke(request, response);
0535:            }
0536:
0537:            /**
0538:             * Rename the existing log file to something else. Then open the
0539:             * old log file name up once again. Intended to be called by a JMX
0540:             * agent.
0541:             *
0542:             *
0543:             * @param newFileName The file name to move the log file entry to
0544:             * @return true if a file was rotated with no error
0545:             */
0546:            public synchronized boolean rotate(String newFileName) {
0547:
0548:                if (currentLogFile != null) {
0549:                    File holder = currentLogFile;
0550:                    close();
0551:                    try {
0552:                        holder.renameTo(new File(newFileName));
0553:                    } catch (Throwable e) {
0554:                        log.error("rotate failed", e);
0555:                    }
0556:
0557:                    /* Make sure date is correct */
0558:                    currentDate = new Date(System.currentTimeMillis());
0559:                    dateStamp = fileDateFormatter.format(currentDate);
0560:
0561:                    open();
0562:                    return true;
0563:                } else {
0564:                    return false;
0565:                }
0566:
0567:            }
0568:
0569:            // -------------------------------------------------------- Private Methods
0570:
0571:            /**
0572:             * Close the currently open log file (if any)
0573:             */
0574:            private synchronized void close() {
0575:                if (writer == null) {
0576:                    return;
0577:                }
0578:                writer.flush();
0579:                writer.close();
0580:                writer = null;
0581:                dateStamp = "";
0582:                currentLogFile = null;
0583:            }
0584:
0585:            /**
0586:             * Log the specified message to the log file, switching files if the date
0587:             * has changed since the previous log call.
0588:             *
0589:             * @param message Message to be logged
0590:             */
0591:            public void log(String message) {
0592:                if (rotatable) {
0593:                    // Only do a logfile switch check once a second, max.
0594:                    long systime = System.currentTimeMillis();
0595:                    if ((systime - rotationLastChecked) > 1000) {
0596:
0597:                        // We need a new currentDate
0598:                        currentDate = new Date(systime);
0599:                        rotationLastChecked = systime;
0600:
0601:                        // Check for a change of date
0602:                        String tsDate = fileDateFormatter.format(currentDate);
0603:
0604:                        // If the date has changed, switch log files
0605:                        if (!dateStamp.equals(tsDate)) {
0606:                            synchronized (this ) {
0607:                                if (!dateStamp.equals(tsDate)) {
0608:                                    close();
0609:                                    dateStamp = tsDate;
0610:                                    open();
0611:                                }
0612:                            }
0613:                        }
0614:                    }
0615:                }
0616:
0617:                /* In case something external rotated the file instead */
0618:                if (checkExists) {
0619:                    synchronized (this ) {
0620:                        if (currentLogFile != null && !currentLogFile.exists()) {
0621:                            try {
0622:                                close();
0623:                            } catch (Throwable e) {
0624:                                log.info("at least this wasn't swallowed", e);
0625:                            }
0626:
0627:                            /* Make sure date is correct */
0628:                            currentDate = new Date(System.currentTimeMillis());
0629:                            dateStamp = fileDateFormatter.format(currentDate);
0630:
0631:                            open();
0632:                        }
0633:                    }
0634:                }
0635:
0636:                // Log this message
0637:                if (writer != null) {
0638:                    writer.println(message);
0639:                    if (!buffered) {
0640:                        writer.flush();
0641:                    }
0642:                }
0643:
0644:            }
0645:
0646:            /**
0647:             * Return the month abbreviation for the specified month, which must
0648:             * be a two-digit String.
0649:             *
0650:             * @param month Month number ("01" .. "12").
0651:             */
0652:            private String lookup(String month) {
0653:                int index;
0654:                try {
0655:                    index = Integer.parseInt(month) - 1;
0656:                } catch (Throwable t) {
0657:                    index = 0; // Can not happen, in theory
0658:                }
0659:                return (months[index]);
0660:            }
0661:
0662:            /**
0663:             * Open the new log file for the date specified by <code>dateStamp</code>.
0664:             */
0665:            protected synchronized void open() {
0666:                // Create the directory if necessary
0667:                File dir = new File(directory);
0668:                if (!dir.isAbsolute())
0669:                    dir = new File(System.getProperty("catalina.base"),
0670:                            directory);
0671:                dir.mkdirs();
0672:
0673:                // Open the current log file
0674:                try {
0675:                    String pathname;
0676:                    // If no rotate - no need for dateStamp in fileName
0677:                    if (rotatable) {
0678:                        pathname = dir.getAbsolutePath() + File.separator
0679:                                + prefix + dateStamp + suffix;
0680:                    } else {
0681:                        pathname = dir.getAbsolutePath() + File.separator
0682:                                + prefix + suffix;
0683:                    }
0684:                    writer = new PrintWriter(new BufferedWriter(new FileWriter(
0685:                            pathname, true), 128000), false);
0686:
0687:                    currentLogFile = new File(pathname);
0688:                } catch (IOException e) {
0689:                    writer = null;
0690:                    currentLogFile = null;
0691:                }
0692:            }
0693:
0694:            /**
0695:             * This method returns a Date object that is accurate to within one second.
0696:             * If a thread calls this method to get a Date and it's been less than 1
0697:             * second since a new Date was created, this method simply gives out the
0698:             * same Date again so that the system doesn't spend time creating Date
0699:             * objects unnecessarily.
0700:             * 
0701:             * @return Date
0702:             */
0703:            private Date getDate() {
0704:                // Only create a new Date once per second, max.
0705:                long systime = System.currentTimeMillis();
0706:                if ((systime - currentMillis) > 1000) {
0707:                    synchronized (this ) {
0708:                        if ((systime - currentMillis) > 1000) {
0709:                            currentDate = new Date(systime);
0710:                            currentMillis = systime;
0711:                        }
0712:                    }
0713:                }
0714:                return currentDate;
0715:            }
0716:
0717:            private String getTimeZone(Date date) {
0718:                if (timezone.inDaylightTime(date)) {
0719:                    return timeZoneDST;
0720:                } else {
0721:                    return timeZoneNoDST;
0722:                }
0723:            }
0724:
0725:            private String calculateTimeZoneOffset(long offset) {
0726:                StringBuffer tz = new StringBuffer();
0727:                if ((offset < 0)) {
0728:                    tz.append("-");
0729:                    offset = -offset;
0730:                } else {
0731:                    tz.append("+");
0732:                }
0733:
0734:                long hourOffset = offset / (1000 * 60 * 60);
0735:                long minuteOffset = (offset / (1000 * 60)) % 60;
0736:
0737:                if (hourOffset < 10)
0738:                    tz.append("0");
0739:                tz.append(hourOffset);
0740:
0741:                if (minuteOffset < 10)
0742:                    tz.append("0");
0743:                tz.append(minuteOffset);
0744:
0745:                return tz.toString();
0746:            }
0747:
0748:            // ------------------------------------------------------ Lifecycle Methods
0749:
0750:            /**
0751:             * Add a lifecycle event listener to this component.
0752:             *
0753:             * @param listener The listener to add
0754:             */
0755:            public void addLifecycleListener(LifecycleListener listener) {
0756:                lifecycle.addLifecycleListener(listener);
0757:            }
0758:
0759:            /**
0760:             * Get the lifecycle listeners associated with this lifecycle. If this
0761:             * Lifecycle has no listeners registered, a zero-length array is returned.
0762:             */
0763:            public LifecycleListener[] findLifecycleListeners() {
0764:                return lifecycle.findLifecycleListeners();
0765:            }
0766:
0767:            /**
0768:             * Remove a lifecycle event listener from this component.
0769:             *
0770:             * @param listener The listener to add
0771:             */
0772:            public void removeLifecycleListener(LifecycleListener listener) {
0773:                lifecycle.removeLifecycleListener(listener);
0774:            }
0775:
0776:            /**
0777:             * Prepare for the beginning of active use of the public methods of this
0778:             * component.  This method should be called after <code>configure()</code>,
0779:             * and before any of the public methods of the component are utilized.
0780:             *
0781:             * @exception LifecycleException if this component detects a fatal error
0782:             *  that prevents this component from being used
0783:             */
0784:            public void start() throws LifecycleException {
0785:
0786:                // Validate and update our current component state
0787:                if (started)
0788:                    throw new LifecycleException(sm
0789:                            .getString("accessLogValve.alreadyStarted"));
0790:                lifecycle.fireLifecycleEvent(START_EVENT, null);
0791:                started = true;
0792:
0793:                // Initialize the timeZone, Date formatters, and currentDate
0794:                timezone = TimeZone.getDefault();
0795:                timeZoneNoDST = calculateTimeZoneOffset(timezone.getRawOffset());
0796:                Calendar calendar = Calendar.getInstance(timezone);
0797:                int offset = calendar.get(Calendar.DST_OFFSET);
0798:                timeZoneDST = calculateTimeZoneOffset(timezone.getRawOffset()
0799:                        + offset);
0800:
0801:                if (fileDateFormat == null || fileDateFormat.length() == 0)
0802:                    fileDateFormat = "yyyy-MM-dd";
0803:                fileDateFormatter = new SimpleDateFormat(fileDateFormat);
0804:                fileDateFormatter.setTimeZone(timezone);
0805:                dayFormatter = new SimpleDateFormat("dd");
0806:                dayFormatter.setTimeZone(timezone);
0807:                monthFormatter = new SimpleDateFormat("MM");
0808:                monthFormatter.setTimeZone(timezone);
0809:                yearFormatter = new SimpleDateFormat("yyyy");
0810:                yearFormatter.setTimeZone(timezone);
0811:                timeFormatter = new SimpleDateFormat("HH:mm:ss");
0812:                timeFormatter.setTimeZone(timezone);
0813:                currentDate = new Date();
0814:                dateStamp = fileDateFormatter.format(currentDate);
0815:                open();
0816:            }
0817:
0818:            /**
0819:             * Gracefully terminate the active use of the public methods of this
0820:             * component.  This method should be the last one called on a given
0821:             * instance of this component.
0822:             *
0823:             * @exception LifecycleException if this component detects a fatal error
0824:             *  that needs to be reported
0825:             */
0826:            public void stop() throws LifecycleException {
0827:
0828:                // Validate and update our current component state
0829:                if (!started)
0830:                    throw new LifecycleException(sm
0831:                            .getString("accessLogValve.notStarted"));
0832:                lifecycle.fireLifecycleEvent(STOP_EVENT, null);
0833:                started = false;
0834:                close();
0835:            }
0836:
0837:            /**
0838:             * AccessLogElement writes the partial message into the buffer.
0839:             */
0840:            protected interface AccessLogElement {
0841:                public void addElement(StringBuffer buf, Date date,
0842:                        Request request, Response response, long time);
0843:
0844:            }
0845:
0846:            /**
0847:             * write local IP address - %A
0848:             */
0849:            protected class LocalAddrElement implements  AccessLogElement {
0850:
0851:                private String value = null;
0852:
0853:                public void addElement(StringBuffer buf, Date date,
0854:                        Request request, Response response, long time) {
0855:                    if (value == null) {
0856:                        synchronized (this ) {
0857:                            try {
0858:                                value = InetAddress.getLocalHost()
0859:                                        .getHostAddress();
0860:                            } catch (Throwable e) {
0861:                                value = "127.0.0.1";
0862:                            }
0863:                        }
0864:                    }
0865:                    buf.append(value);
0866:                }
0867:            }
0868:
0869:            /**
0870:             * write remote IP address - %a
0871:             */
0872:            protected class RemoteAddrElement implements  AccessLogElement {
0873:                public void addElement(StringBuffer buf, Date date,
0874:                        Request request, Response response, long time) {
0875:                    buf.append(request.getRemoteAddr());
0876:                }
0877:            }
0878:
0879:            /**
0880:             * write remote host name - %h
0881:             */
0882:            protected class HostElement implements  AccessLogElement {
0883:                public void addElement(StringBuffer buf, Date date,
0884:                        Request request, Response response, long time) {
0885:                    buf.append(request.getRemoteHost());
0886:                }
0887:            }
0888:
0889:            /**
0890:             * write remote logical username from identd (always returns '-') - %l
0891:             */
0892:            protected class LogicalUserNameElement implements  AccessLogElement {
0893:                public void addElement(StringBuffer buf, Date date,
0894:                        Request request, Response response, long time) {
0895:                    buf.append('-');
0896:                }
0897:            }
0898:
0899:            /**
0900:             * write request protocol - %H
0901:             */
0902:            protected class ProtocolElement implements  AccessLogElement {
0903:                public void addElement(StringBuffer buf, Date date,
0904:                        Request request, Response response, long time) {
0905:                    buf.append(request.getProtocol());
0906:                }
0907:            }
0908:
0909:            /**
0910:             * write remote user that was authenticated (if any), else '-' - %u
0911:             */
0912:            protected class UserElement implements  AccessLogElement {
0913:                public void addElement(StringBuffer buf, Date date,
0914:                        Request request, Response response, long time) {
0915:                    if (request != null) {
0916:                        String value = request.getRemoteUser();
0917:                        if (value != null) {
0918:                            buf.append(value);
0919:                        } else {
0920:                            buf.append('-');
0921:                        }
0922:                    } else {
0923:                        buf.append('-');
0924:                    }
0925:                }
0926:            }
0927:
0928:            /**
0929:             * write date and time, in Common Log Format - %t
0930:             */
0931:            protected class DateAndTimeElement implements  AccessLogElement {
0932:                private Date currentDate = new Date(0);
0933:
0934:                private String currentDateString = null;
0935:
0936:                public void addElement(StringBuffer buf, Date date,
0937:                        Request request, Response response, long time) {
0938:                    if (currentDate != date) {
0939:                        synchronized (this ) {
0940:                            if (currentDate != date) {
0941:                                StringBuffer current = new StringBuffer(32);
0942:                                current.append('[');
0943:                                current.append(dayFormatter.format(date)); // Day
0944:                                current.append('/');
0945:                                current.append(lookup(monthFormatter
0946:                                        .format(date))); // Month
0947:                                current.append('/');
0948:                                current.append(yearFormatter.format(date)); // Year
0949:                                current.append(':');
0950:                                current.append(timeFormatter.format(date)); // Time
0951:                                current.append(' ');
0952:                                current.append(getTimeZone(date)); // Timezone
0953:                                current.append(']');
0954:                                currentDateString = current.toString();
0955:                                currentDate = date;
0956:                            }
0957:                        }
0958:                    }
0959:                    buf.append(currentDateString);
0960:                }
0961:            }
0962:
0963:            /**
0964:             * write first line of the request (method and request URI) - %r
0965:             */
0966:            protected class RequestElement implements  AccessLogElement {
0967:                public void addElement(StringBuffer buf, Date date,
0968:                        Request request, Response response, long time) {
0969:                    if (request != null) {
0970:                        buf.append(request.getMethod());
0971:                        buf.append(' ');
0972:                        buf.append(request.getRequestURI());
0973:                        if (request.getQueryString() != null) {
0974:                            buf.append('?');
0975:                            buf.append(request.getQueryString());
0976:                        }
0977:                        buf.append(' ');
0978:                        buf.append(request.getProtocol());
0979:                    } else {
0980:                        buf.append("- - ");
0981:                    }
0982:                }
0983:            }
0984:
0985:            /**
0986:             * write HTTP status code of the response - %s
0987:             */
0988:            protected class HttpStatusCodeElement implements  AccessLogElement {
0989:                public void addElement(StringBuffer buf, Date date,
0990:                        Request request, Response response, long time) {
0991:                    if (response != null) {
0992:                        buf.append(response.getStatus());
0993:                    } else {
0994:                        buf.append('-');
0995:                    }
0996:                }
0997:            }
0998:
0999:            /**
1000:             * write local port on which this request was received - %p
1001:             */
1002:            protected class LocalPortElement implements  AccessLogElement {
1003:                public void addElement(StringBuffer buf, Date date,
1004:                        Request request, Response response, long time) {
1005:                    buf.append(request.getServerPort());
1006:                }
1007:            }
1008:
1009:            /**
1010:             * write bytes sent, excluding HTTP headers - %b, %B
1011:             */
1012:            protected class ByteSentElement implements  AccessLogElement {
1013:                private boolean conversion;
1014:
1015:                /**
1016:                 * if conversion is true, write '-' instead of 0 - %b
1017:                 */
1018:                public ByteSentElement(boolean conversion) {
1019:                    this .conversion = conversion;
1020:                }
1021:
1022:                public void addElement(StringBuffer buf, Date date,
1023:                        Request request, Response response, long time) {
1024:                    int length = response.getContentCount();
1025:                    if (length <= 0 && conversion) {
1026:                        buf.append('-');
1027:                    } else {
1028:                        buf.append(length);
1029:                    }
1030:                }
1031:            }
1032:
1033:            /**
1034:             * write request method (GET, POST, etc.) - %m
1035:             */
1036:            protected class MethodElement implements  AccessLogElement {
1037:                public void addElement(StringBuffer buf, Date date,
1038:                        Request request, Response response, long time) {
1039:                    if (request != null) {
1040:                        buf.append(request.getMethod());
1041:                    }
1042:                }
1043:            }
1044:
1045:            /**
1046:             * write time taken to process the request - %D, %T
1047:             */
1048:            protected class ElapsedTimeElement implements  AccessLogElement {
1049:                private boolean millis;
1050:
1051:                /**
1052:                 * if millis is true, write time in millis - %D
1053:                 * if millis is false, write time in seconds - %T
1054:                 */
1055:                public ElapsedTimeElement(boolean millis) {
1056:                    this .millis = millis;
1057:                }
1058:
1059:                public void addElement(StringBuffer buf, Date date,
1060:                        Request request, Response response, long time) {
1061:                    if (millis) {
1062:                        buf.append(time);
1063:                    } else {
1064:                        // second
1065:                        buf.append(time / 1000);
1066:                        buf.append('.');
1067:                        int remains = (int) (time % 1000);
1068:                        buf.append(remains / 100);
1069:                        remains = remains % 100;
1070:                        buf.append(remains / 10);
1071:                        buf.append(remains % 10);
1072:                    }
1073:                }
1074:            }
1075:
1076:            /**
1077:             * write Query string (prepended with a '?' if it exists) - %q
1078:             */
1079:            protected class QueryElement implements  AccessLogElement {
1080:                public void addElement(StringBuffer buf, Date date,
1081:                        Request request, Response response, long time) {
1082:                    String query = null;
1083:                    if (request != null)
1084:                        query = request.getQueryString();
1085:                    if (query != null) {
1086:                        buf.append('?');
1087:                        buf.append(query);
1088:                    }
1089:                }
1090:            }
1091:
1092:            /**
1093:             * write user session ID - %S
1094:             */
1095:            protected class SessionIdElement implements  AccessLogElement {
1096:                public void addElement(StringBuffer buf, Date date,
1097:                        Request request, Response response, long time) {
1098:                    if (request != null) {
1099:                        if (request.getSession(false) != null) {
1100:                            buf.append(request.getSessionInternal(false)
1101:                                    .getIdInternal());
1102:                        } else {
1103:                            buf.append('-');
1104:                        }
1105:                    } else {
1106:                        buf.append('-');
1107:                    }
1108:                }
1109:            }
1110:
1111:            /**
1112:             * write requested URL path - %U
1113:             */
1114:            protected class RequestURIElement implements  AccessLogElement {
1115:                public void addElement(StringBuffer buf, Date date,
1116:                        Request request, Response response, long time) {
1117:                    if (request != null) {
1118:                        buf.append(request.getRequestURI());
1119:                    } else {
1120:                        buf.append('-');
1121:                    }
1122:                }
1123:            }
1124:
1125:            /**
1126:             * write local server name - %v
1127:             */
1128:            protected class LocalServerNameElement implements  AccessLogElement {
1129:                public void addElement(StringBuffer buf, Date date,
1130:                        Request request, Response response, long time) {
1131:                    buf.append(request.getServerName());
1132:                }
1133:            }
1134:
1135:            /**
1136:             * write any string
1137:             */
1138:            protected class StringElement implements  AccessLogElement {
1139:                private String str;
1140:
1141:                public StringElement(String str) {
1142:                    this .str = str;
1143:                }
1144:
1145:                public void addElement(StringBuffer buf, Date date,
1146:                        Request request, Response response, long time) {
1147:                    buf.append(str);
1148:                }
1149:            }
1150:
1151:            /**
1152:             * write incoming headers - %{xxx}i
1153:             */
1154:            protected class HeaderElement implements  AccessLogElement {
1155:                private String header;
1156:
1157:                public HeaderElement(String header) {
1158:                    this .header = header;
1159:                }
1160:
1161:                public void addElement(StringBuffer buf, Date date,
1162:                        Request request, Response response, long time) {
1163:                    buf.append(request.getHeader(header));
1164:                }
1165:            }
1166:
1167:            /**
1168:             * write a specific cookie - %{xxx}c
1169:             */
1170:            protected class CookieElement implements  AccessLogElement {
1171:                private String header;
1172:
1173:                public CookieElement(String header) {
1174:                    this .header = header;
1175:                }
1176:
1177:                public void addElement(StringBuffer buf, Date date,
1178:                        Request request, Response response, long time) {
1179:                    String value = "-";
1180:                    Cookie[] c = request.getCookies();
1181:                    if (c != null) {
1182:                        for (int i = 0; i < c.length; i++) {
1183:                            if (header.equals(c[i].getName())) {
1184:                                value = c[i].getValue();
1185:                                break;
1186:                            }
1187:                        }
1188:                    }
1189:                    buf.append(value);
1190:                }
1191:            }
1192:
1193:            /**
1194:             * write an attribute in the ServletRequest - %{xxx}r
1195:             */
1196:            protected class RequestAttributeElement implements  AccessLogElement {
1197:                private String header;
1198:
1199:                public RequestAttributeElement(String header) {
1200:                    this .header = header;
1201:                }
1202:
1203:                public void addElement(StringBuffer buf, Date date,
1204:                        Request request, Response response, long time) {
1205:                    Object value = null;
1206:                    if (request != null) {
1207:                        value = request.getAttribute(header);
1208:                    } else {
1209:                        value = "??";
1210:                    }
1211:                    if (value != null) {
1212:                        if (value instanceof  String) {
1213:                            buf.append((String) value);
1214:                        } else {
1215:                            buf.append(value.toString());
1216:                        }
1217:                    } else {
1218:                        buf.append('-');
1219:                    }
1220:                }
1221:            }
1222:
1223:            /**
1224:             * write an attribute in the HttpSession - %{xxx}s
1225:             */
1226:            protected class SessionAttributeElement implements  AccessLogElement {
1227:                private String header;
1228:
1229:                public SessionAttributeElement(String header) {
1230:                    this .header = header;
1231:                }
1232:
1233:                public void addElement(StringBuffer buf, Date date,
1234:                        Request request, Response response, long time) {
1235:                    Object value = null;
1236:                    if (null != request) {
1237:                        HttpSession sess = request.getSession(false);
1238:                        if (null != sess)
1239:                            value = sess.getAttribute(header);
1240:                    } else {
1241:                        value = "??";
1242:                    }
1243:                    if (value != null) {
1244:                        if (value instanceof  String) {
1245:                            buf.append((String) value);
1246:                        } else {
1247:                            buf.append(value.toString());
1248:                        }
1249:                    } else {
1250:                        buf.append('-');
1251:                    }
1252:                }
1253:            }
1254:
1255:            /**
1256:             * parse pattern string and create the array of AccessLogElement
1257:             */
1258:            protected AccessLogElement[] createLogElements() {
1259:                List<AccessLogElement> list = new ArrayList<AccessLogElement>();
1260:                boolean replace = false;
1261:                StringBuffer buf = new StringBuffer();
1262:                for (int i = 0; i < pattern.length(); i++) {
1263:                    char ch = pattern.charAt(i);
1264:                    if (replace) {
1265:                        /*
1266:                         * For code that processes {, the behavior will be ... if I do
1267:                         * not enounter a closing } - then I ignore the {
1268:                         */
1269:                        if ('{' == ch) {
1270:                            StringBuffer name = new StringBuffer();
1271:                            int j = i + 1;
1272:                            for (; j < pattern.length()
1273:                                    && '}' != pattern.charAt(j); j++) {
1274:                                name.append(pattern.charAt(j));
1275:                            }
1276:                            if (j + 1 < pattern.length()) {
1277:                                /* the +1 was to account for } which we increment now */
1278:                                j++;
1279:                                list.add(createAccessLogElement(
1280:                                        name.toString(), pattern.charAt(j)));
1281:                                i = j; /* Since we walked more than one character */
1282:                            } else {
1283:                                // D'oh - end of string - pretend we never did this
1284:                                // and do processing the "old way"
1285:                                list.add(createAccessLogElement(ch));
1286:                            }
1287:                        } else {
1288:                            list.add(createAccessLogElement(ch));
1289:                        }
1290:                        replace = false;
1291:                    } else if (ch == '%') {
1292:                        replace = true;
1293:                        list.add(new StringElement(buf.toString()));
1294:                        buf = new StringBuffer();
1295:                    } else {
1296:                        buf.append(ch);
1297:                    }
1298:                }
1299:                if (buf.length() > 0) {
1300:                    list.add(new StringElement(buf.toString()));
1301:                }
1302:                return (AccessLogElement[]) list
1303:                        .toArray(new AccessLogElement[0]);
1304:            }
1305:
1306:            /**
1307:             * create an AccessLogElement implementation which needs header string
1308:             */
1309:            private AccessLogElement createAccessLogElement(String header,
1310:                    char pattern) {
1311:                switch (pattern) {
1312:                case 'i':
1313:                    return new HeaderElement(header);
1314:                case 'c':
1315:                    return new CookieElement(header);
1316:                case 'r':
1317:                    return new RequestAttributeElement(header);
1318:                case 's':
1319:                    return new SessionAttributeElement(header);
1320:                default:
1321:                    return new StringElement("???");
1322:                }
1323:            }
1324:
1325:            /**
1326:             * create an AccessLogElement implementation
1327:             */
1328:            private AccessLogElement createAccessLogElement(char pattern) {
1329:                switch (pattern) {
1330:                case 'a':
1331:                    return new RemoteAddrElement();
1332:                case 'A':
1333:                    return new LocalAddrElement();
1334:                case 'b':
1335:                    return new ByteSentElement(true);
1336:                case 'B':
1337:                    return new ByteSentElement(false);
1338:                case 'D':
1339:                    return new ElapsedTimeElement(true);
1340:                case 'h':
1341:                    return new HostElement();
1342:                case 'H':
1343:                    return new ProtocolElement();
1344:                case 'l':
1345:                    return new LogicalUserNameElement();
1346:                case 'm':
1347:                    return new MethodElement();
1348:                case 'p':
1349:                    return new LocalPortElement();
1350:                case 'q':
1351:                    return new QueryElement();
1352:                case 'r':
1353:                    return new RequestElement();
1354:                case 's':
1355:                    return new HttpStatusCodeElement();
1356:                case 'S':
1357:                    return new SessionIdElement();
1358:                case 't':
1359:                    return new DateAndTimeElement();
1360:                case 'T':
1361:                    return new ElapsedTimeElement(false);
1362:                case 'u':
1363:                    return new UserElement();
1364:                case 'U':
1365:                    return new RequestURIElement();
1366:                case 'v':
1367:                    return new LocalServerNameElement();
1368:                default:
1369:                    return new StringElement("???" + pattern + "???");
1370:                }
1371:            }
1372:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.