1 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 ; 28 import java.util.regex.Matcher ; 29 import java.io.File ; 30 import java.io.FilenameFilter ; 31 import java.io.RandomAccessFile ; 32 import java.nio.channels.FileChannel ; 33 import java.nio.MappedByteBuffer ; 34 import java.nio.CharBuffer ; 35 import java.nio.charset.Charset ; 36 import java.text.SimpleDateFormat ; 37 import java.text.ParseException ; 38 39 44 public class TomcatLogManagerImpl implements TomcatLogManager { 45 private final static Log log = LogFactory.getLog(TomcatLogManagerImpl.class); 46 47 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]))"); 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 private final static String FILE_SEPARATOR_UNIX_STYLE = "/"; 57 private final static String FILE_SEPARATOR_WIN_STYLE = "\\"; 58 59 private final static Pattern FULL_LINE_PATTERN = Pattern.compile("^.*", Pattern.MULTILINE); 61 private final static Pattern 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 ACCESS_LOG_DATE_FORMAT = "dd/MMM/yyyy:HH:mm:ss ZZZZ"; 70 private final static String 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 86 public String [] 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 []) logNames.toArray(new String [logNames.size()]); 96 } 97 98 106 public String [] getLogFileNames(String logName) { 107 List names = new ArrayList(); 108 109 File [] 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 []) names.toArray(new String [names.size()]); 118 } 119 120 129 private File [] getLogFiles(String logName) { 130 File [] logFiles = null; 131 132 try { 133 String 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 logFile = serverInfo.resolvePath(logName); 141 142 File parent = new File (logFile).getParentFile(); 143 144 if (parent != null) { 145 logFiles = parent.listFiles(new PatternFilenameFilter(fileNamePattern)); 146 } 147 } catch (Exception e) { 148 log.error("Exception attempting to locate Tomcat log files", e); 149 logFiles = new File [0]; 150 } 151 return logFiles; 152 } 153 154 161 public SearchResults getMatchingItems(String logName, String host, String user, String method, String uri, 162 Date startDate, Date endDate, Integer skipResults, Integer maxResults) { 163 164 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 File logFiles[] = getLogFiles(logName); 179 180 if (logFiles !=null) { 181 for (int i = 0; i < logFiles.length; i++) { 182 fileLineCount = 0; 183 try { 184 String fileName = logFiles[i].getName(); 186 Matcher fileDate = FILENAME_DATE_PATTERN.matcher(fileName); 187 fileDate.find(); 188 SimpleDateFormat simpleFileDate = new SimpleDateFormat (LOG_FILE_NAME_FORMAT); 189 long logFileTime = simpleFileDate.parse(fileDate.group(GROUP_FILENAME_FULL_DATE)).getTime(); 190 Date logFileDate = new Date(logFileTime); 191 192 if ( (start==0 && end==0) 194 || (start>0 && start<=logFileTime && end>0 && end>=logFileTime)) { 195 196 RandomAccessFile raf = new RandomAccessFile (logFiles[i], "r"); 198 FileChannel fc = raf.getChannel(); 199 MappedByteBuffer bb = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size()); 200 CharBuffer cb = Charset.forName("US-ASCII").decode(bb); Matcher lines = FULL_LINE_PATTERN.matcher(cb); 202 Matcher target = ACCESS_LOG_PATTERN.matcher(""); 203 SimpleDateFormat format = (start == 0 && end == 0) ? null : new SimpleDateFormat (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 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 e) { 237 } 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 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 []{"ServerInfo","LogGBeans"}); 271 GBEAN_INFO = infoFactory.getBeanInfo(); 272 } 273 274 public static GBeanInfo getGBeanInfo() { 275 return GBEAN_INFO; 276 } 277 278 282 static class PatternFilenameFilter implements FilenameFilter { 283 Pattern pattern; 284 285 PatternFilenameFilter(String 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 file, String fileName) { 296 return pattern.matcher(fileName).matches(); 297 } 298 } 299 300 339 } 340 | Popular Tags |