KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > tomcat > TomcatLogManagerImpl


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 package org.apache.geronimo.tomcat;
18
19 import org.apache.geronimo.gbean.GBeanInfo;
20 import org.apache.geronimo.gbean.GBeanInfoBuilder;
21 import org.apache.geronimo.system.serverinfo.ServerInfo;
22 import org.apache.commons.logging.Log;
23 import org.apache.commons.logging.LogFactory;
24 import org.apache.catalina.valves.AccessLogValve;
25
26 import java.util.*;
27 import java.util.regex.Pattern JavaDoc;
28 import java.util.regex.Matcher JavaDoc;
29 import java.io.File JavaDoc;
30 import java.io.FilenameFilter JavaDoc;
31 import java.io.RandomAccessFile JavaDoc;
32 import java.nio.channels.FileChannel JavaDoc;
33 import java.nio.MappedByteBuffer JavaDoc;
34 import java.nio.CharBuffer JavaDoc;
35 import java.nio.charset.Charset JavaDoc;
36 import java.text.SimpleDateFormat JavaDoc;
37 import java.text.ParseException JavaDoc;
38
39 /**
40  * Tomcat implementation of the WebAccessLog management interface.
41  *
42  * @version $Rev: 476049 $ $Date: 2006-11-16 23:35:17 -0500 (Thu, 16 Nov 2006) $
43  */

44 public class TomcatLogManagerImpl implements TomcatLogManager {
45     private final static Log log = LogFactory.getLog(TomcatLogManagerImpl.class);
46
47     // Pattern that matches the date in the logfile name
48
private final static Pattern JavaDoc FILENAME_DATE_PATTERN = Pattern.compile("[-_ /.](((19|20)\\d\\d)[-_ /.](0[1-9]|1[012])[-_ /.](0[1-9]|[12][0-9]|3[01]))");
49     private final static int GROUP_FILENAME_FULL_DATE = 1;
50     private final static int GROUP_FILENAME_YEAR = 2;
51     private final static int GROUP_FILENAME_MONTH = 4;
52     private final static int GROUP_FILENAME_DAY = 5;
53     // NOTE: The file separators are specified here rather than using something like File.separator because
54
// they are hard coded in config plans and sometimes in java code itself rather than being dependent
55
// upon the OS. This should be fixed someday, but for now we will manually check for either format.
56
private final static String JavaDoc FILE_SEPARATOR_UNIX_STYLE = "/";
57     private final static String JavaDoc FILE_SEPARATOR_WIN_STYLE = "\\";
58
59     // Pattern that matches a single line (used to calculate line numbers)
60
private final static Pattern JavaDoc FULL_LINE_PATTERN = Pattern.compile("^.*", Pattern.MULTILINE);
61     private final static Pattern JavaDoc ACCESS_LOG_PATTERN = Pattern.compile("(\\S*) (\\S*) (\\S*) \\[(.*)\\] \\\"(\\S*) (\\S*).*?\\\" (\\S*) (\\S*).*");
62     private final static int GROUP_HOST = 1;
63     private final static int GROUP_USER = 3;
64     private final static int GROUP_DATE = 4;
65     private final static int GROUP_METHOD = 5;
66     private final static int GROUP_URI = 6;
67     private final static int GROUP_RESPONSE_CODE = 7;
68     private final static int GROUP_RESPONSE_LENGTH = 8;
69     private final static String JavaDoc ACCESS_LOG_DATE_FORMAT = "dd/MMM/yyyy:HH:mm:ss ZZZZ";
70     private final static String JavaDoc LOG_FILE_NAME_FORMAT = "yyyy-MM-dd";
71     private final Collection logGbeans;
72     private final ServerInfo serverInfo;
73
74     public TomcatLogManagerImpl(ServerInfo serverInfo, Collection logGbeans) {
75         this.serverInfo = serverInfo;
76         this.logGbeans = logGbeans;
77     }
78
79     /**
80      * Gets the name of all logs used by this system. Typically there
81      * is only one, but specialized cases may use more.
82      *
83      * @return An array of all log names
84      *
85      */

86     public String JavaDoc[] getLogNames() {
87         List logNames = new ArrayList();
88         for (Iterator it = logGbeans.iterator(); it.hasNext();) {
89             ValveGBean logGBean = (ValveGBean) it.next();
90             AccessLogValve logFile = (AccessLogValve) logGBean.getInternalObject();
91             if(logFile != null) {
92                 logNames.add( "var/catalina/logs/"+logFile.getPrefix()+LOG_FILE_NAME_FORMAT+logFile.getSuffix());
93             }
94         }
95         return (String JavaDoc[]) logNames.toArray(new String JavaDoc[logNames.size()]);
96     }
97
98     /**
99      * Gets the names of all log files for this log name.
100      *
101      * @param logName The name of the log for which to return the specific file names.
102      *
103      * @return An array of log file names
104      *
105      */

106     public String JavaDoc[] getLogFileNames(String JavaDoc logName) {
107         List names = new ArrayList();
108
109         // Find all the files for this logName
110
File JavaDoc[] logFiles = getLogFiles(logName);
111
112         if (logFiles !=null) {
113             for (int i = 0; i < logFiles.length; i++) {
114                 names.add(logFiles[i].getName());
115             }
116         }
117         return (String JavaDoc[]) names.toArray(new String JavaDoc[names.size()]);
118     }
119
120     /**
121      * Gets the name of all log files used by this log. Typically there
122      * is only one, but specialized cases may use more.
123      *
124      * @param logName The name of the log for which to return the specific files.
125      *
126      * @return An array of all log file names
127      *
128      */

129     private File JavaDoc[] getLogFiles(String JavaDoc logName) {
130         File JavaDoc[] logFiles = null;
131
132         try {
133             String JavaDoc fileNamePattern = logName;
134             if (fileNamePattern.indexOf(FILE_SEPARATOR_UNIX_STYLE) > -1) {
135                 fileNamePattern = fileNamePattern.substring(fileNamePattern.lastIndexOf(FILE_SEPARATOR_UNIX_STYLE) + 1);
136             } else if (fileNamePattern.indexOf(FILE_SEPARATOR_WIN_STYLE) > -1) {
137                 fileNamePattern = fileNamePattern.substring(fileNamePattern.lastIndexOf(FILE_SEPARATOR_WIN_STYLE) + 1);
138             }
139
140             String JavaDoc logFile = serverInfo.resolvePath(logName);
141
142             File JavaDoc parent = new File JavaDoc(logFile).getParentFile();
143
144             if (parent != null) {
145                 logFiles = parent.listFiles(new PatternFilenameFilter(fileNamePattern));
146             }
147         } catch (Exception JavaDoc e) {
148             log.error("Exception attempting to locate Tomcat log files", e);
149             logFiles = new File JavaDoc[0];
150         }
151         return logFiles;
152     }
153
154     /**
155      * Searches the log for records matching the specified parameters. The
156      * maximum results returned will be the lesser of 1000 and the
157      * provided maxResults argument.
158      *
159      * @see #MAX_SEARCH_RESULTS
160      */

161     public SearchResults getMatchingItems(String JavaDoc logName, String JavaDoc host, String JavaDoc user, String JavaDoc method, String JavaDoc uri,
162                                           Date startDate, Date endDate, Integer JavaDoc skipResults, Integer JavaDoc maxResults) {
163
164         // Clean up the arguments so we know what we've really got
165
if(host != null && host.equals("")) host = null;
166         if(user != null && user.equals("")) user = null;
167         if(method != null && method.equals("")) method = null;
168         if(uri != null && uri.equals("")) uri = null;
169
170         long start = startDate == null ? 0 : startDate.getTime();
171         long end = endDate == null ? 0 : endDate.getTime();
172
173         List list = new LinkedList();
174         boolean capped = false;
175         int lineCount = 0, fileLineCount = 0;
176
177         // Find all the files for this logName
178
File JavaDoc logFiles[] = getLogFiles(logName);
179
180         if (logFiles !=null) {
181             for (int i = 0; i < logFiles.length; i++) {
182                 fileLineCount = 0;
183                 try {
184                     // Obtain the date for the current log file
185
String JavaDoc fileName = logFiles[i].getName();
186                     Matcher JavaDoc fileDate = FILENAME_DATE_PATTERN.matcher(fileName);
187                     fileDate.find();
188                     SimpleDateFormat JavaDoc simpleFileDate = new SimpleDateFormat JavaDoc(LOG_FILE_NAME_FORMAT);
189                     long logFileTime = simpleFileDate.parse(fileDate.group(GROUP_FILENAME_FULL_DATE)).getTime();
190                     Date logFileDate = new Date(logFileTime);
191
192                     // Check if the dates are null (ignore) or fall within the search range
193
if ( (start==0 && end==0)
194                        || (start>0 && start<=logFileTime && end>0 && end>=logFileTime)) {
195
196                         // It's in the range, so process the file
197
RandomAccessFile JavaDoc raf = new RandomAccessFile JavaDoc(logFiles[i], "r");
198                         FileChannel JavaDoc fc = raf.getChannel();
199                         MappedByteBuffer JavaDoc bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
200                         CharBuffer JavaDoc cb = Charset.forName("US-ASCII").decode(bb); //todo: does Tomcat use a different charset on a foreign PC?
201
Matcher JavaDoc lines = FULL_LINE_PATTERN.matcher(cb);
202                         Matcher JavaDoc target = ACCESS_LOG_PATTERN.matcher("");
203                         SimpleDateFormat JavaDoc format = (start == 0 && end == 0) ? null : new SimpleDateFormat JavaDoc(ACCESS_LOG_DATE_FORMAT);
204                         int max = maxResults == null ? MAX_SEARCH_RESULTS : Math.min(maxResults.intValue(), MAX_SEARCH_RESULTS);
205
206                         while(lines.find()) {
207                             ++lineCount;
208                             ++fileLineCount;
209                             if(capped) {
210                                 continue;
211                             }
212                             CharSequence JavaDoc line = cb.subSequence(lines.start(), lines.end());
213                             target.reset(line);
214                             if(target.find()) {
215                                 if(host != null && !host.equals(target.group(GROUP_HOST))) {
216                                     continue;
217                                 }
218                                 if(user != null && !user.equals(target.group(GROUP_USER))) {
219                                     continue;
220                                 }
221                                 if(method != null && !method.equals(target.group(GROUP_METHOD))) {
222                                     continue;
223                                 }
224                                 if(uri != null && !target.group(GROUP_URI).startsWith(uri)) {
225                                     continue;
226                                 }
227                                 if(format != null) {
228                                     try {
229                                         long entry = format.parse(target.group(GROUP_DATE)).getTime();
230                                         if(start > entry) {
231                                             continue;
232                                         }
233                                         if(end > 0 && end < entry) {
234                                             continue;
235                                         }
236                                     } catch (ParseException JavaDoc e) {
237                                         // can't read the date, guess this record counts.
238
}
239                                 }
240                                 if(skipResults != null && skipResults.intValue() > lineCount) {
241                                     continue;
242                                 }
243                                 if(list.size() > max) {
244                                     capped = true;
245                                     continue;
246                                 }
247                                 list.add(new LogMessage(fileLineCount,line.toString()));
248                             }
249                         }
250                         fc.close();
251                         raf.close();
252                     }
253                 } catch (Exception JavaDoc e) {
254                     log.error("Unexpected error processing logs", e);
255                 }
256             }
257         }
258         return new SearchResults(lineCount, (LogMessage[]) list.toArray(new LogMessage[list.size()]), capped);
259     }
260
261
262     public static final GBeanInfo GBEAN_INFO;
263
264     static {
265         GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic("Tomcat Log Manager", TomcatLogManagerImpl.class);
266         infoFactory.addReference("LogGBeans", ValveGBean.class);
267         infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
268         infoFactory.addInterface(TomcatLogManager.class);
269
270         infoFactory.setConstructor(new String JavaDoc[]{"ServerInfo","LogGBeans"});
271         GBEAN_INFO = infoFactory.getBeanInfo();
272     }
273
274     public static GBeanInfo getGBeanInfo() {
275         return GBEAN_INFO;
276     }
277
278     /*
279      * Static inner class implementation of java.io.Filename. This will help us
280      * filter for only the files that we are interested in.
281      */

282     static class PatternFilenameFilter implements FilenameFilter JavaDoc {
283         Pattern JavaDoc pattern;
284
285         PatternFilenameFilter(String JavaDoc fileNamePattern) {
286             fileNamePattern = fileNamePattern.replaceAll("yyyy", "\\\\d{4}");
287             fileNamePattern = fileNamePattern.replaceAll("yy", "\\\\d{2}");
288             fileNamePattern = fileNamePattern.replaceAll("mm", "\\\\d{2}");
289             fileNamePattern = fileNamePattern.replaceAll("MM", "\\\\d{2}");
290             fileNamePattern = fileNamePattern.replaceAll("dd", "\\\\d{2}")
291                     + ".*";
292             this.pattern = Pattern.compile(fileNamePattern);
293         }
294
295         public boolean accept(File JavaDoc file, String JavaDoc fileName) {
296             return pattern.matcher(fileName).matches();
297         }
298     }
299
300 /*
301     public static void main(String[] args) {
302         String jetty = "127.0.0.1 - - [07/Sep/2005:19:54:41 +0000] \"GET /console/ HTTP/1.1\" 302 0 \"-\" \"Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.10) Gecko/20050715 Firefox/1.0.6 SUSE/1.0.6-4.1\" -";
303         String tomcat = "127.0.0.1 - - [07/Sep/2005:15:51:18 -0500] \"GET /console/portal/server/server_info HTTP/1.1\" 200 11708";
304
305         SimpleDateFormat format = new SimpleDateFormat("dd/MMM/yyyy:HH:mm:ss ZZZZ");
306         try {
307             Pattern p = Pattern.compile("(\\S*) (\\S*) (\\S*) \\[(.*)\\] \\\"(\\S*) (\\S*).*?\\\" (\\S*) (\\S*).*");
308             Matcher m = p.matcher(jetty);
309             if(m.matches()) {
310                 System.out.println("Group 1: "+m.group(1)); // client
311                 System.out.println("Group 2: "+m.group(2)); // ?? server host?
312                 System.out.println("Group 3: "+m.group(3)); // username
313                 System.out.println("Group 4: "+format.parse(m.group(4))); // date
314                 System.out.println("Group 5: "+m.group(5)); // method
315                 System.out.println("Group 5: "+m.group(6)); // URI
316                 System.out.println("Group 6: "+m.group(7)); // response code
317                 System.out.println("Group 7: "+m.group(8)); // response length
318             } else {
319                 System.out.println("No match");
320             }
321             m = p.matcher(tomcat);
322             if(m.matches()) {
323                 System.out.println("Group 1: "+m.group(1));
324                 System.out.println("Group 2: "+m.group(2));
325                 System.out.println("Group 3: "+m.group(3));
326                 System.out.println("Group 4: "+format.parse(m.group(4)));
327                 System.out.println("Group 5: "+m.group(5)); // method
328                 System.out.println("Group 5: "+m.group(6)); // URI
329                 System.out.println("Group 6: "+m.group(7)); // response code
330                 System.out.println("Group 7: "+m.group(8)); // response length
331             } else {
332                 System.out.println("No match");
333             }
334         } catch (ParseException e) {
335             e.printStackTrace();
336         }
337     }
338 */

339 }
340
Popular Tags