public static CompareResult compare(List<String> oldIds, List<String> ids) { CompareResult compareResult = new CompareResult(); int diff = oldIds.size() - ids.size(); if (diff == 0 && isTheSame(oldIds, ids)) { compareResult.setResult(Result.SAME_ITEMS); return compareResult; } else if (diff == -1) { int position = getAddedItemPosition(oldIds, ids); if (position != -1) { compareResult.setResult(Result.ONE_ITEM_ADDED); compareResult.setChangedPosition(position); return compareResult; } } else if (diff == 1) { int position = getRemovedItemPosition(oldIds, ids); if (position != -1) { compareResult.setResult(Result.ONE_ITEM_REMOVED); compareResult.setChangedPosition(position); return compareResult; } } compareResult.setResult(Result.MANY_ITEMS_CHANGED); return compareResult; }
public void execute() { if (destDir == null) throw new BuildException("The destdir attribute must be set"); if (type == null) throw new BuildException("The type attribute must be set"); log("Comparing files"); final Map<String, SourceFile> vmFiles = vmDirs.scanJavaFiles(getProject()); final Map<String, SourceFile> classpathFiles = classpathDirs.scanJavaFiles(getProject()); final Map<String, SourceFile> vmSpecificFiles = vmSpecificDirs.scanJavaFiles(getProject()); final TreeSet<String> allFiles = new TreeSet<String>(); final Map<String, String> packageDiffs = new TreeMap<String, String>(); allFiles.addAll(vmFiles.keySet()); allFiles.addAll(classpathFiles.keySet()); try { destDir.mkdirs(); int n = Runtime.getRuntime().availableProcessors() * 2; ExecutorService es = Executors.newFixedThreadPool(n); class CompareCallable implements Callable<Collection<CompareResult>> { private Collection<String> files; CompareCallable(Collection<String> files) { this.files = files; } @Override public Collection<CompareResult> call() throws Exception { ArrayList<CompareResult> results = new ArrayList<CompareResult>(); for (String name : files) { SourceFile cpFile = classpathFiles.get(name); final SourceFile vmFile = vmFiles.get(name); final SourceFile vmSpecificFile = vmSpecificFiles.get(name); if (vmSpecificFile != null) { // File is found as vm specific source results.add(new VmSpecificResult(name, vmSpecificFile.getReportName())); } else if (vmFile == null) { // file is not found as vmspecific source, nor as vm source if (!cpFile.isIgnoreMissing()) { results.add( new MissingResult(name, cpFile.getReportName(), type, getFlags(cpFile))); } } else if (cpFile == null) { // File is not found in classpath sources results.add(new MissingResult(name, vmFile.getReportName(), "vm", new Flags())); } else { // We have both the classpath version and the vm version. cpFile = cpFile.getBestFileForTarget(vmFile.getTarget()); // Let's compare them final String diffFileName = vmFile.getReportName() + ".diff"; Flags rc = runDiff(vmFile, cpFile, diffFileName, packageDiffs); switch (rc.asInt() & ~FLAGS_MASK) { case NO_CHANGE: break; case NEEDS_MERGE: results.add( new NeedsMergeResult( name, vmFile.getReportName(), vmFile.getTarget(), diffFileName, rc.mask(FLAGS_MASK))); break; default: throw new RuntimeException("Invalid rc " + rc); } if (rc.isSet(FLAG_VM_SPECIFIC)) { results.add(new CounterResult(name, "FLAG_VM_SPECIFIC")); } if (rc.isSet(FLAG_CLASSPATH_BUGFIX)) { results.add(new CounterResult(name, "FLAG_CLASSPATH_BUGFIX")); } if (rc.isSet(FLAG_NATIVE)) { results.add(new CounterResult(name, "FLAG_NATIVE")); } if (rc.isSet(FLAG_JNODE)) { results.add(new CounterResult(name, "FLAG_JNODE")); } if (rc.getBugIDs().length > 0) { results.add( new ClasspathBugsResult(name, vmFile.getReportName(), vmFile.getTarget(), rc)); } } } return results; } } ArrayList<String> al = new ArrayList<String>(); al.addAll(allFiles); CompareCallable[] tasks = new CompareCallable[n]; for (int i = 0; i < n; i++) { tasks[i] = new CompareCallable(al.subList(i * al.size() / n, (i + 1) * al.size() / n)); } List<Future<Collection<CompareResult>>> futures = es.invokeAll(Arrays.asList(tasks)); es.shutdown(); es.awaitTermination(1, TimeUnit.HOURS); ArrayList<CompareResult> results = new ArrayList<CompareResult>(); for (Future<Collection<CompareResult>> future : futures) { if (future.isDone()) { try { results.addAll(future.get()); } catch (ExecutionException x) { throw new RuntimeException(x); } } else { throw new RuntimeException("Future is not done: " + future); } } Collections.sort(results); log("Generating reports"); final File outBugsFile = new File(destDir, "bugfix.html"); final PrintWriter outBugs = new PrintWriter(new FileWriter(outBugsFile)); reportHeader(outBugs, "Class", "Target", "Classpath bugs"); final File outFile = new File(destDir, "index.html"); final PrintWriter out = new PrintWriter(new FileWriter(outFile)); reportHeader(out, "Class", "Target", "Merge status"); int missingInCp = 0; int missingInVm = 0; int needsMerge = 0; int diffVmSpecific = 0; int diffClasspathBugfix = 0; int diffNative = 0; int diffJNode = 0; int vmSpecific = 0; for (CompareResult result : results) { if (result instanceof VmSpecificResult) { result.reportResult(out); vmSpecific++; } else if (result instanceof MissingResult) { result.reportResult(out); MissingResult missingResult = (MissingResult) result; if (missingResult.type.equals("vm")) { missingInCp++; } else { missingInVm++; } } else if (result instanceof NeedsMergeResult) { result.reportResult(out); needsMerge++; } else if (result instanceof CounterResult) { CounterResult counterResult = (CounterResult) result; if (counterResult.counter.equals("FLAG_VM_SPECIFIC")) { diffVmSpecific++; } else if (counterResult.counter.equals("FLAG_CLASSPATH_BUGFIX")) { diffClasspathBugfix++; } else if (counterResult.counter.equals("FLAG_NATIVE")) { diffNative++; } else if (counterResult.counter.equals("FLAG_JNODE")) { diffJNode++; } } else if (result instanceof ClasspathBugsResult) { result.reportResult(outBugs); } else { new RuntimeException("Unknown compare result: " + result); } } // Package diffs for (Map.Entry<String, String> entry : packageDiffs.entrySet()) { final String pkg = entry.getKey(); final String diff = entry.getValue(); final String diffFileName = pkg + ".pkgdiff"; processPackageDiff(diffFileName, pkg, diff); reportPackageDiff(out, pkg, diffFileName, getFlags(diff)); } out.println("</table><p/>"); // Summary out.println("<a name='summary'/><h2>Summary</h2>"); if (missingInCp > 0) { out.println("Found " + missingInCp + " files missing in " + type + "</br>"); log("Found " + missingInCp + " files missing in " + type); } if (missingInVm > 0) { out.println("Found " + missingInVm + " files missing in vm<br/>"); log("Found " + missingInVm + " files missing in vm"); } if (needsMerge > 0) { out.println("Found " + needsMerge + " files that needs merging<br/>"); log("Found " + needsMerge + " files that needs merging"); } if (diffVmSpecific > 0) { out.println("Found " + diffVmSpecific + " VM specific differences<br/>"); log("Found " + diffVmSpecific + " VM specific differences"); } if (vmSpecific > 0) { out.println("Found " + vmSpecific + " VM specific files<br/>"); log("Found " + vmSpecific + " VM specific files"); } if (diffClasspathBugfix > 0) { out.println( "Found " + diffClasspathBugfix + " local <a href=\"bugfix.html\">classpath bugfixes</a><br/>"); log("Found " + diffClasspathBugfix + " local classpath bugfixes"); } if (diffNative > 0) { out.println("Found " + diffNative + " changes with native in it<br/>"); log("Found " + diffNative + " changes with native in it"); } if (diffJNode > 0) { out.println("Found " + diffJNode + " changes with JNode in it<br/>"); log("Found " + diffJNode + " changes with JNode in it"); } reportFooter(out); out.flush(); out.close(); reportFooter(outBugs); outBugs.flush(); outBugs.close(); } catch (IOException ex) { throw new BuildException(ex); } catch (InterruptedException ex) { throw new BuildException(ex); } }