1 19 20 package org.netbeans.modules.tomcat5.util; 21 22 import java.io.BufferedReader ; 23 import java.io.File ; 24 import java.io.FileReader ; 25 import java.io.IOException ; 26 import java.text.DateFormat ; 27 import java.text.SimpleDateFormat ; 28 import java.util.Collections ; 29 import java.util.Date ; 30 import java.util.EventListener ; 31 import java.util.Iterator ; 32 import java.util.LinkedList ; 33 import java.util.List ; 34 import org.netbeans.api.java.classpath.GlobalPathRegistry; 35 import org.netbeans.modules.tomcat5.TomcatManager; 36 import org.netbeans.modules.tomcat5.util.LogSupport.LineInfo; 37 import org.openide.ErrorManager; 38 import org.openide.windows.IOProvider; 39 import org.openide.windows.InputOutput; 40 import org.openide.windows.OutputWriter; 41 42 51 public class LogViewer extends Thread { 52 private volatile boolean stop = false; 53 private InputOutput inOut; 54 private OutputWriter writer; 55 private OutputWriter errorWriter; 56 private File directory; 57 private String prefix; 58 private String suffix; 59 private boolean isTimestamped; 60 private boolean takeFocus; 61 62 private ContextLogSupport logSupport; 63 private String catalinaWorkDir; 64 private String webAppContext; 65 private boolean isStarted; 66 67 70 private List stopListeners = Collections.synchronizedList(new LinkedList ()); 71 72 private String displayName; 73 74 95 public LogViewer(File catalinaDir, String catalinaWorkDir, String webAppContext, 96 String className, String directory, String prefix, String suffix, 97 boolean isTimestamped, boolean takeFocus) throws UnsupportedLoggerException { 98 super("LogViewer - Thread"); if (catalinaDir == null) { 100 throw new NullPointerException (); 101 } 102 if (catalinaWorkDir == null) { 103 throw new NullPointerException (); 104 } 105 if (className != null && !"org.apache.catalina.logger.FileLogger".equals(className)) { throw new UnsupportedLoggerException(className); 107 } 108 if (directory != null) { 109 this.directory = new File (directory); 110 if (!this.directory.isAbsolute()) { 111 this.directory = new File (catalinaDir, directory); 112 } 113 } else { 114 this.directory = new File (catalinaDir, "logs"); } 116 if (prefix != null) { 117 this.prefix = prefix; 118 } else { 119 this.prefix = "catalina."; } 121 if (suffix != null) { 122 this.suffix = suffix; 123 } else { 124 this.suffix = ".log"; } 126 this.isTimestamped = isTimestamped; 127 this.takeFocus = takeFocus; 128 this.catalinaWorkDir = catalinaWorkDir; 129 this.webAppContext = webAppContext; 130 logSupport = new ContextLogSupport(catalinaWorkDir, webAppContext); 131 setDaemon(true); 132 } 133 134 public void setDisplayName(String displayName) { 135 this.displayName = displayName; 136 } 137 138 141 public void close() { 142 synchronized(this) { 143 stop = true; 144 notify(); 145 } 146 } 147 148 public boolean equals(Object obj) { 149 if (this == obj) { 150 return true; 151 } 152 if (obj instanceof LogViewer) { 153 LogViewer anotherLogViewer = (LogViewer)obj; 154 if (catalinaWorkDir.equals(anotherLogViewer.catalinaWorkDir) 155 && (((webAppContext != null) && webAppContext.equals(anotherLogViewer.webAppContext)) 156 || (webAppContext == anotherLogViewer.webAppContext)) 157 && directory.equals(anotherLogViewer.directory) 158 && prefix.equals(anotherLogViewer.prefix) 159 && suffix.equals(anotherLogViewer.suffix) 160 && isTimestamped) { 161 return true; 162 } 163 } 164 return false; 165 } 166 167 172 public boolean isOpen() { 173 InputOutput io = inOut; 174 return !(io == null || stop || (isStarted && io.isClosed())); 175 } 176 177 180 public void takeFocus() { 181 InputOutput io = inOut; 182 if (io != null) { 183 io.select(); 184 } 185 } 186 187 private File getLogFile(String timestamp) throws IOException { 188 File f = new File (directory, prefix + timestamp + suffix); 189 f.createNewFile(); return f; 191 } 192 193 private String getTimestamp() { 194 DateFormat df = new SimpleDateFormat ("yyyy-MM-dd"); return df.format(new Date ()); 196 } 197 198 private void processLine(String line) { 199 ContextLogSupport.LineInfo lineInfo = logSupport.analyzeLine(line); 200 if (lineInfo.isError()) { 201 if (lineInfo.isAccessible()) { 202 try { 203 errorWriter.println(line, logSupport.getLink(lineInfo.message(), lineInfo.path(), lineInfo.line())); 204 } catch (IOException ex) { 205 ErrorManager.getDefault().notify(ex); 206 } 207 } else { 208 errorWriter.println(line); 209 } 210 } else { 211 writer.println(line); 212 } 213 } 214 215 public void run() { 216 if (displayName == null) { 217 displayName = this.prefix; 219 int trailingDot = displayName.lastIndexOf('.'); 220 if (trailingDot > -1) { 221 displayName = displayName.substring(0, trailingDot); 222 } 223 } 224 inOut = IOProvider.getDefault().getIO(displayName, false); 225 try { 226 inOut.getOut().reset(); 227 } 228 catch (IOException e) { 229 ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e); 231 } 232 inOut.select(); 233 writer = inOut.getOut(); 234 errorWriter = inOut.getErr(); 235 isStarted = true; 236 237 String timestamp = getTimestamp(); 238 String oldTimestamp = timestamp; 239 try { 240 File logFile = getLogFile(timestamp); 241 BufferedReader reader = new BufferedReader (new FileReader (logFile)); 242 try { 243 while (!stop && !inOut.isClosed()) { 244 timestamp = getTimestamp(); 246 if (!timestamp.equals(oldTimestamp)) { 247 oldTimestamp = timestamp; 248 reader.close(); 249 logFile = getLogFile(timestamp); 250 reader = new BufferedReader (new FileReader (logFile)); 251 } 252 int count = 0; 253 boolean updated = false; 256 while (reader.ready() && count++ < 1024) { 257 processLine(reader.readLine()); 258 updated = true; 259 } 260 if (updated) { 261 writer.flush(); 262 errorWriter.flush(); 263 if (takeFocus) { 264 inOut.select(); 265 } 266 } 267 try { 269 synchronized(this) { 270 if (!stop && !inOut.isClosed()) { 271 wait(100); 272 } 273 } 274 } catch(InterruptedException ex) { 275 } 277 } 278 } finally { 279 reader.close(); 280 } 281 } catch (IOException ex) { 282 TomcatManager.ERR.notify(ex); 283 } finally { 284 writer.close(); 285 } 286 fireLogViewerStopListener(); 287 logSupport.detachAnnotation(); 288 } 289 290 296 public void addLogViewerStopListener(LogViewerStopListener listener) { 297 stopListeners.add(listener); 298 } 299 300 306 public void removeAllLogViewerStopListener() { 307 stopListeners.removeAll(stopListeners); 308 } 309 310 private void fireLogViewerStopListener() { 311 for (Iterator i = stopListeners.iterator(); i.hasNext();) { 312 ((LogViewerStopListener)i.next()).callOnStop(); 313 } 314 } 315 316 320 public static interface LogViewerStopListener extends EventListener { 321 public void callOnStop(); 322 } 323 324 328 static class ContextLogSupport extends LogSupport { 329 private final String CATALINA_WORK_DIR; 330 private String context = null; 331 private String prevMessage = null; 332 private static final String STANDARD_CONTEXT = "StandardContext["; private static final int STANDARD_CONTEXT_LENGTH = STANDARD_CONTEXT.length(); 334 private GlobalPathRegistry globalPathReg = GlobalPathRegistry.getDefault(); 335 336 337 public ContextLogSupport(String catalinaWork, String webAppContext) { 338 CATALINA_WORK_DIR = catalinaWork; 339 context = webAppContext; 340 } 341 342 public LineInfo analyzeLine(String logLine) { 343 String path = null; 344 int line = -1; 345 String message = null; 346 boolean error = false; 347 boolean accessible = false; 348 349 logLine = logLine.trim(); 350 int lineLenght = logLine.length(); 351 352 if (logLine.startsWith("/")) { 354 error = true; 355 int colonIdx = logLine.indexOf(':'); 356 if (colonIdx > -1) { 357 path = logLine.substring(0, colonIdx); 358 accessible = true; 359 if (lineLenght > colonIdx) { 360 int nextColonIdx = logLine.indexOf(':', colonIdx + 1); 361 if (nextColonIdx > -1) { 362 String lineNum = logLine.substring(colonIdx + 1, nextColonIdx); 363 try { 364 line = Integer.valueOf(lineNum).intValue(); 365 } catch(NumberFormatException nfe) { 366 TomcatManager.ERR.notify(ErrorManager.INFORMATIONAL, nfe); 368 } 369 if (lineLenght > nextColonIdx) { 370 message = logLine.substring(nextColonIdx + 1, lineLenght); 371 } 372 } 373 } 374 } 375 } 376 else if (lineLenght > 3 && Character.isLetter(logLine.charAt(0)) 378 && (logLine.charAt(1) == ':') && (logLine.charAt(2) == '\\')) { 379 error = true; 380 int secondColonIdx = logLine.indexOf(':', 2); 381 if (secondColonIdx > -1) { 382 path = logLine.substring(0, secondColonIdx); 383 accessible = true; 384 if (lineLenght > secondColonIdx) { 385 int thirdColonIdx = logLine.indexOf(':', secondColonIdx + 1); 386 if (thirdColonIdx > -1) { 387 String lineNum = logLine.substring(secondColonIdx + 1, thirdColonIdx); 388 try { 389 line = Integer.valueOf(lineNum).intValue(); 390 } catch(NumberFormatException nfe) { TomcatManager.ERR.notify(ErrorManager.INFORMATIONAL, nfe); 392 } 393 if (lineLenght > thirdColonIdx) { 394 message = logLine.substring(thirdColonIdx + 1, lineLenght); 395 } 396 } 397 } 398 } 399 } 400 else if (logLine.startsWith("at ") && lineLenght > 3) { 403 error = true; 404 int parenthIdx = logLine.indexOf('('); 405 if (parenthIdx > -1) { 406 String classWithMethod = logLine.substring(3, parenthIdx); 407 int lastDotIdx = classWithMethod.lastIndexOf('.'); 408 if (lastDotIdx > -1) { 409 int lastParenthIdx = logLine.lastIndexOf(')'); 410 int lastColonIdx = logLine.lastIndexOf(':'); 411 if (lastParenthIdx > -1 && lastColonIdx > -1) { 412 String lineNum = logLine.substring(lastColonIdx + 1, lastParenthIdx); 413 try { 414 line = Integer.valueOf(lineNum).intValue(); 415 } catch(NumberFormatException nfe) { TomcatManager.ERR.notify(ErrorManager.INFORMATIONAL, nfe); 417 } 418 message = prevMessage; 419 } 420 int firstDolarIdx = classWithMethod.indexOf('$'); String className = classWithMethod.substring(0, firstDolarIdx > -1 ? firstDolarIdx : lastDotIdx); 422 path = className.replace('.','/') + ".java"; accessible = globalPathReg.findResource(path) != null; 424 if (className.startsWith("org.apache.jsp.") && context != null) { if (context != null) { 426 String contextPath = context.equals("/") 427 ? "/_" : context; 429 path = CATALINA_WORK_DIR + contextPath + "/" + path; 430 accessible = new File (path).exists(); 431 } 432 } 433 } 434 } 435 } 436 else { 438 prevMessage = logLine; 439 int stdContextIdx = logLine.indexOf(STANDARD_CONTEXT); 441 int lBracketIdx = -1; 442 if (stdContextIdx > -1) { 443 lBracketIdx = stdContextIdx + STANDARD_CONTEXT_LENGTH; 444 } 445 int rBracketIdx = logLine.indexOf(']'); 446 if (lBracketIdx > -1 && rBracketIdx > -1 && rBracketIdx > lBracketIdx) { 447 context = logLine.substring(lBracketIdx, rBracketIdx); 448 } 449 } 450 return new LineInfo(path, line, message, error, accessible); 451 } 452 } 453 } | Popular Tags |