| package org.eclipse.ganymede.webgen; |
| |
| import java.io.PrintWriter; |
| import java.util.Map; |
| import java.util.regex.Matcher; |
| import java.util.regex.Pattern; |
| |
| public class LogLine { |
| public String line; |
| |
| public int linenumber; |
| |
| public Status status; |
| |
| public Blame blame; |
| |
| String anchor; |
| |
| private static int nextanchor = 1; |
| |
| public LogLine(String s, int number) { |
| this.linenumber = number; |
| this.line = s; |
| this.status = Status.unknown; |
| } |
| |
| public String addAnchor() { |
| this.anchor = "" + nextanchor++; |
| return this.anchor; |
| } |
| |
| public String getAnchor() { |
| return this.anchor; |
| } |
| public Blame getBlame() { |
| return this.blame; |
| } |
| |
| public void write_log_line(PrintWriter writer) { |
| if (status.isFail()) { |
| writer.print("<span style=\"background-color: " |
| + WebPageColors.fail_color() + ";\">"); |
| } |
| if (status.isSuccess()) { |
| writer.print("<span style=\"background-color: " |
| + WebPageColors.success_color() + ";\">"); |
| } |
| writer.print("<code>"); |
| if (this.anchor != null) { |
| writer.print("<a name=\"" + this.anchor + "\"></a>"); |
| } |
| writer.print(line); |
| writer.print("</code>"); |
| if (status.isFail() || status.isSuccess()) { |
| writer.print("</span>"); |
| } |
| } |
| |
| private static Pattern pGood = Pattern.compile("(^BUILD SUCCESSFUL)" |
| + "|(\\s*\\[java\\]\\s*(INFO:\\s*)?Import complete)"); |
| private static Pattern pBad = Pattern.compile("([Ee]xception)" |
| + "|([Ee]rror)" + "|([Ff]ail)" |
| + "|(^verify\\.properties\\.error:$)"); |
| private static String sSpecialCasesForPlatform = |
| "|(ContinueOnError: The following ID was not found, so was skipped, and is not on mir+or site: .*(org\\.eclipse\\.swt\\.gtk|org\\.eclipse\\.equinox\\.launcher\\.gtk))" |
| + "|(ContinueOnError: The following ID was not found, so was skipped, and is not on mir+or site: .*(org\\.eclipse\\.swt\\.win32\\.win32\\.ia64|org\\.eclipse\\.equinox\\.launcher\\.win32\\.win32\\.ia64|org\\.eclipse\\.core\\.filesystem\\.win32\\.ia64|org\\.eclipse\\.core\\.resources\\.win32\\.ia64))" |
| + "|(\\s*\\[java\\]\\s*java.lang.UnsatisfiedLinkError: localfile_1_0_0)" |
| ; |
| private static Pattern pNotBad = Pattern.compile("('--continueonerror')" |
| + "|(so this may not be an error)" |
| + "|(Workspace was not properly initialized or has already shutdown)" |
| + sSpecialCasesForPlatform |
| ); |
| private static Pattern pOk = Pattern |
| .compile("" |
| + "(^Buildfile: .*$)" |
| + "|(^generate.bm.artifacts:)" |
| + "|(^\\s*\\[mkdir\\] Created dir: )" |
| + "|(^\\s*\\[delete\\] Deleting directory )" |
| + "|(^\\s*\\[echo\\]\\s*\".*\\.sc\")" |
| + "|(^\\s*\\[java\\]\\s*Creating directory )" |
| + "|(^\\s*\\[java\\]\\s*generate '--outputdir' )" |
| + "|(^\\s*\\[java\\]\\s*Generating artifacts from file:)" |
| + "|(^\\s*\\[java\\]\\s*Writing generated artifacts to )" |
| + "|(^\\s*\\[java\\]\\s*Platform install location: )" |
| + "|(^\\s*\\[java\\]\\s*Generation complete)" |
| + "|(^resolve.cquery:)" |
| + "|(\\s*\\[java\\]\\s*resolve '--continueonerror' )" |
| + "|(\\s*\\[java\\]\\s*Using workspace at )" |
| + "|(\\s*\\[java\\]\\s*Platform install location: )" |
| + "|(\\s*\\[java\\]\\s*Found searchPath default for component )" |
| + "|(\\s*\\[java\\]\\s*Provider url\\(.*\\): Found a match for component )" |
| + "|(\\s*\\[java\\]\\s*Found searchPath .*for component )" |
| + "|(\\s*\\[java\\]\\s*Provider site.feature(.*): Found a match for .* using version designator )" |
| + "|(\\s*\\[java\\]\\s*Query complete.)" |
| + "|(\\s*\\[java\\]\\s*(INFO:\\s*)?Could not load library: .*This library provides platform-specific optimizations for certain file system operations. This library is not present on all platforms, so this may not be an error. )" |
| + "|(\\s*\\[java\\]\\s*java.lang.UnsatisfiedLinkError: localfile_1_0_0)" |
| + "|(\\s*\\[java\\]\\s*at )" //too bad we have to 'ok' this, because this is really a stack dump and it should be an error |
| //but this log line parser isn't clever enough to know that stack dumps following the localfile_1_0_0 line |
| //are _not_ errors whereas all the rest of the stack dumps _are_ errors. |
| + "|(^materialize:)" |
| + "|(Workspace was not properly initialized or has already shutdown)" |
| + "|(\\s*\\[java\\]\\s*import )" |
| + "|(\\s*\\[java\\]\\s*Using workspace at )" |
| + "|(\\s*\\[java\\]\\s*Platform install location: )" |
| + "|(\\s*\\[java\\]\\s*Installing features finished. Updating categories )" |
| + "|(\\s*\\[java\\]\\s*Updating categories finished. Updating site description )" |
| + "|(\\s*\\[java\\]\\s*Updating site description finished. Saving site.xml )" |
| + "|(\\s*\\[java\\]\\s*Mirroring feature )" |
| + "|(\\s*\\[java\\]\\s*Getting plugin entries for )" |
| + "|(\\s*\\[java\\]\\s*Getting non plugin entries for )" |
| + "|(\\s*\\[java\\]\\s*Getting included features for )" |
| + "|(\\s*\\[java\\]\\s*Downloading feature archives for )" |
| + "|(\\s*\\[java\\]\\s*Downloading plug-in archives for )" |
| + "|(\\s*\\[java\\]\\s*Downloading non plug-in archives for )" |
| + "|(\\s*\\[java\\]\\s*Installing child features for )" |
| + "|(\\s*\\[java\\]\\s*Storing plug-in archives for )" |
| + "|(\\s*\\[java\\]\\s*Storing non plug-in archives for )" |
| + "|(\\s*\\[java\\]\\s*Storing feature archives for )" |
| + "|(\\s*\\[java\\]\\s*Adding feature )" |
| + "|(\\s*\\[java\\]\\s*Feature .* added to site.xml)" |
| + "|(\\s*\\[java\\]\\s*Feature .* already exists\\.\\s*Skipping downloading\\.)" |
| + "|(\\s*\\[java\\]\\s*(INFO:?\\s*)?TAG-ID \\d+ =)" |
| + "|(\\s*\\[java\\]\\s*INFO:?\\s+)" |
| + "|(^\\s*\\[java\\]\\s*$)" |
| + "|(^\\s+\\[copy\\]\\s*Copying\\s+\\d+\\s+file)" |
| + "|(^Total time: \\d+)" + "|(^get\\.properties:$)" |
| + "|(^verify\\.properties\\..*:$)" + "|(^\\s*$)" |
| |
| /* |
| * Special case errors |
| */ |
| + "|(\\s*\\[java\\]\\s*(ERROR:\\s*)?Digest could not be parsed:Unable to retrieve remote reference)" |
| + "|(\\s*\\[java\\]\\s*(ERROR:\\s*)?Digest could not be parsed:Element type \"includes\" must be followed by either attribute specifications)" |
| + sSpecialCasesForPlatform |
| ); |
| |
| public Status scan_for_status() { |
| Matcher mBad = pBad.matcher(this.line); |
| if (mBad.find()) { |
| Matcher mNotBad = pNotBad.matcher(this.line); |
| if (!mNotBad.find()) { |
| this.status = Status.getFail(); |
| this.status.setErrorBookmark(this.addAnchor()); |
| this.status.setBlame(this.blame); |
| return this.status; |
| } |
| } |
| Matcher mGood = pGood.matcher(this.line); |
| if (mGood.find()) { |
| this.status = Status.success; |
| } else { |
| Matcher mOk = pOk.matcher(this.line); |
| if (!mOk.find()) { |
| this.status = Status.getFail(); |
| this.status.setErrorBookmark(this.addAnchor()); |
| this.status.setBlame(this.blame); |
| return this.status; |
| } |
| } |
| return this.status; |
| } |
| |
| private static final Pattern pNeedBlame = Pattern |
| .compile("(^\\s*\\[java\\]\\s+(?:ERROR\\s+)?\\[(\\d+)\\] :)" |
| + "|(^\\s*\\[java\\]\\s+(?:WARNING\\s+)?\\[(\\d+)\\] :)"); |
| |
| public void assignBlameIfNeeded(Map<String, Blame> blames) { |
| Matcher m = pNeedBlame.matcher(this.line); |
| if (m.find()) { |
| if( m.group(2) != null ) |
| this.blame = blames.get(m.group(2)); |
| if( m.group(4) != null ) |
| this.blame = blames.get(m.group(4)); |
| } |
| } |
| |
| private static final Pattern pTAGID = Pattern |
| .compile("^\\s*\\[java\\]\\s+(?:INFO:?\\s+)?TAG-ID (\\d+) = project: (\\S+),"); |
| |
| public Blame parseBlame() { |
| Matcher m = pTAGID.matcher(this.line); |
| if (m.find()) |
| return new Blame(m.group(1), m.group(2)); |
| else |
| return null; |
| } |
| } |