KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > jetty6 > requestlog > JettyLogManagerImpl


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.jetty6.requestlog;
18
19 import java.io.File JavaDoc;
20 import java.io.FilenameFilter JavaDoc;
21 import java.io.RandomAccessFile JavaDoc;
22 import java.nio.CharBuffer JavaDoc;
23 import java.nio.MappedByteBuffer JavaDoc;
24 import java.nio.channels.FileChannel JavaDoc;
25 import java.nio.charset.Charset JavaDoc;
26 import java.text.ParseException JavaDoc;
27 import java.text.SimpleDateFormat JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Collection JavaDoc;
30 import java.util.Date JavaDoc;
31 import java.util.Iterator JavaDoc;
32 import java.util.LinkedList JavaDoc;
33 import java.util.List JavaDoc;
34 import java.util.regex.Matcher JavaDoc;
35 import java.util.regex.Pattern JavaDoc;
36
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.apache.geronimo.gbean.GBeanInfo;
40 import org.apache.geronimo.gbean.GBeanInfoBuilder;
41 import org.apache.geronimo.system.serverinfo.ServerInfo;
42
43 /**
44  * Jetty implementation of the WebAccessLog management interface.
45  *
46  * @version $Rev: 482336 $ $Date: 2006-12-04 15:12:19 -0500 (Mon, 04 Dec 2006) $
47  */

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

90     public String JavaDoc[] getLogNames() {
91         List JavaDoc logNames = new ArrayList JavaDoc();
92         for (Iterator JavaDoc it = logGbeans.iterator(); it.hasNext();) {
93             JettyRequestLog jettyLog = (JettyRequestLog) it.next();
94             if(jettyLog.getFilename() != null) {
95                 logNames.add(jettyLog.getFilename());
96             }
97         }
98         return (String JavaDoc[]) logNames.toArray(new String JavaDoc[logNames.size()]);
99     }
100
101     /**
102      * Gets the names of all log files for this log name.
103      *
104      * @param logName The name of the log for which to return the specific file names.
105      *
106      * @return An array of log file names
107      *
108      */

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

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

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

284     static class PatternFilenameFilter implements FilenameFilter JavaDoc {
285         Pattern JavaDoc pattern;
286         //todo: put this pattern in a GBean parameter?
287
PatternFilenameFilter(String JavaDoc fileNamePattern) {
288             fileNamePattern = fileNamePattern.replaceAll("yyyy", "\\\\d{4}");
289             fileNamePattern = fileNamePattern.replaceAll("yy", "\\\\d{2}");
290             fileNamePattern = fileNamePattern.replaceAll("mm", "\\\\d{2}");
291             fileNamePattern = fileNamePattern.replaceAll("dd", "\\\\d{2}");
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
Popular Tags