1 17 package org.apache.geronimo.jetty6.requestlog; 18 19 import java.io.File ; 20 import java.io.FilenameFilter ; 21 import java.io.RandomAccessFile ; 22 import java.nio.CharBuffer ; 23 import java.nio.MappedByteBuffer ; 24 import java.nio.channels.FileChannel ; 25 import java.nio.charset.Charset ; 26 import java.text.ParseException ; 27 import java.text.SimpleDateFormat ; 28 import java.util.ArrayList ; 29 import java.util.Collection ; 30 import java.util.Date ; 31 import java.util.Iterator ; 32 import java.util.LinkedList ; 33 import java.util.List ; 34 import java.util.regex.Matcher ; 35 import java.util.regex.Pattern ; 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 48 public class JettyLogManagerImpl implements JettyLogManager { 49 private final static Log log = LogFactory.getLog(JettyLogManagerImpl.class); 50 51 private final static Pattern 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 private final static String FILE_SEPARATOR_UNIX_STYLE = "/"; 61 private final static String FILE_SEPARATOR_WIN_STYLE = "\\"; 62 63 private final static Pattern FULL_LINE_PATTERN = Pattern.compile("^.*", Pattern.MULTILINE); 65 private final static Pattern 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 ACCESS_LOG_DATE_FORMAT = "dd/MMM/yyyy:HH:mm:ss ZZZZ"; 74 private final static String LOG_FILE_NAME_FORMAT = "yyyy_MM_dd"; 75 private final Collection logGbeans; 76 private final ServerInfo serverInfo; 77 78 public JettyLogManagerImpl(ServerInfo serverInfo, Collection logGbeans) { 79 this.serverInfo = serverInfo; 80 this.logGbeans = logGbeans; 81 } 82 83 90 public String [] getLogNames() { 91 List logNames = new ArrayList (); 92 for (Iterator 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 []) logNames.toArray(new String [logNames.size()]); 99 } 100 101 109 public String [] getLogFileNames(String logName) { 110 List names = new ArrayList (); 111 112 File [] 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 []) names.toArray(new String [names.size()]); 121 } 122 123 132 private File [] getLogFiles(String logName) { 133 File [] logFiles = null; 134 135 try { 136 String 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 logFile = serverInfo.resolvePath(logName); 144 145 File parent = new File (logFile).getParentFile(); 146 147 if (parent != null) { 148 logFiles = parent.listFiles(new PatternFilenameFilter(fileNamePattern)); 149 } 150 } catch (Exception e) { 151 log.error("Exception attempting to locate Jetty log files", e); 152 logFiles = new File [0]; 153 } 154 return logFiles; 155 } 156 157 164 public SearchResults getMatchingItems(String logName, String host, String user, String method, String uri, Date startDate, 165 Date endDate, Integer skipResults, Integer maxResults) { 166 167 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 list = new LinkedList (); 177 boolean capped = false; 178 int lineCount = 0, fileCount = 0; 179 180 File logFiles[] = getLogFiles(logName); 182 183 if (logFiles !=null) { 184 for (int i = 0; i < logFiles.length; i++) { 185 fileCount = 0; 186 try { 187 String fileName = logFiles[i].getName(); 189 Matcher fileDate = FILENAME_DATE_PATTERN.matcher(fileName); 190 fileDate.find(); 191 SimpleDateFormat simpleFileDate = new SimpleDateFormat (LOG_FILE_NAME_FORMAT); 192 long logFileTime = simpleFileDate.parse(fileDate.group(GROUP_FILENAME_FULL_DATE)).getTime(); 193 194 if ( (start==0 && end==0) 196 || (start>0 && start<=logFileTime && end>0 && end>=logFileTime)) { 197 198 RandomAccessFile raf = new RandomAccessFile (logFiles[i], "r"); 200 FileChannel fc = raf.getChannel(); 201 MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); 202 CharBuffer cb = Charset.forName("US-ASCII").decode(bb); Matcher lines = FULL_LINE_PATTERN.matcher(cb); 204 Matcher target = ACCESS_LOG_PATTERN.matcher(""); 205 SimpleDateFormat format = (start == 0 && end == 0) ? null : new SimpleDateFormat (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 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 e) { 239 } 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 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 []{"ServerInfo","LogGBeans"}); 273 GBEAN_INFO = infoFactory.getBeanInfo(); 274 } 275 276 public static GBeanInfo getGBeanInfo() { 277 return GBEAN_INFO; 278 } 279 280 284 static class PatternFilenameFilter implements FilenameFilter { 285 Pattern pattern; 286 PatternFilenameFilter(String 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 file, String fileName) { 296 return pattern.matcher(fileName).matches(); 297 } 298 } 299 } 300 | Popular Tags |