--- old/src/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java 2014-08-09 00:28:48.967821782 +0200 +++ new/src/share/classes/com/sun/tools/sjavac/comp/PubapiVisitor.java 2014-08-09 00:28:48.847825264 +0200 @@ -25,8 +25,11 @@ package com.sun.tools.sjavac.comp; +import java.util.ArrayList; +import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.LinkedList; import javax.lang.model.element.Modifier; import javax.lang.model.element.ExecutableElement; import javax.lang.model.element.TypeElement; @@ -44,17 +47,46 @@ */ public class PubapiVisitor extends ElementScanner9 { - StringBuffer sb; - // Important that it is 1! Part of protocol over wire, silly yes. - // Fix please. - int indent = 1; + // The pubapi is stored here. + List api = new LinkedList(); + // The hash of the pubapi (excluding paths to jars/classes and their timestamp) + int hash; + // Indentation level. + int indent = 0; + // The class location info is for example: + // ZipFileIndexFileObject[/home/fredrik/bin/jdk1.8.0/lib/tools.jar(com/sun/tools/javac/comp/Resolve.class) 1396702502000 + // ie the jfileobj.toString() + " " + jfileobj.getLastModified() + String class_loc_info = ""; + + // If true, then store full public api information, not just the hash. + // Makes it much easier to debug any public api bugs. + boolean debugPubapi = false; - public PubapiVisitor(StringBuffer sb) { - this.sb = sb; + String depth(int l) { + return "________________________________".substring(0, l); } - String depth(int l) { - return " ".substring(0, l); + public void classLocInfo(String s) { + class_loc_info = " "+s; + } + + public void construct(TypeElement e) { + visit(e); + hash = 0; + List sorted_api = new ArrayList<>(); + sorted_api.addAll(api); + // Why sort here? Because we want the same pubapi hash to be generated + // for both a source compile and a classpath extraction. + Collections.sort(sorted_api); + + for (String s : sorted_api) { + hash ^= s.hashCode(); + } + api = new LinkedList(); + api.add(0, "PUBAPI "+e.getQualifiedName()+" "+Integer.toString(Math.abs(hash),16)+class_loc_info); + if (debugPubapi) { + api.addAll(sorted_api); + } } @Override @@ -62,7 +94,7 @@ if (e.getModifiers().contains(Modifier.PUBLIC) || e.getModifiers().contains(Modifier.PROTECTED)) { - sb.append(depth(indent) + "TYPE " + e.getQualifiedName() + "\n"); + api.add(depth(indent) + "!TYPE " + e.getQualifiedName()); indent += 2; Void v = super.visitType(e, p); indent -= 2; @@ -75,8 +107,7 @@ public Void visitVariable(VariableElement e, Void p) { if (e.getModifiers().contains(Modifier.PUBLIC) || e.getModifiers().contains(Modifier.PROTECTED)) { - sb.append(depth(indent)).append("VAR ") - .append(makeVariableString(e)).append("\n"); + api.add(depth(indent)+"VAR "+makeVariableString(e)); } // Safe to not recurse here, because the only thing // to visit here is the constructor of a variable declaration. @@ -90,8 +121,7 @@ public Void visitExecutable(ExecutableElement e, Void p) { if (e.getModifiers().contains(Modifier.PUBLIC) || e.getModifiers().contains(Modifier.PROTECTED)) { - sb.append(depth(indent)).append("METHOD ") - .append(makeMethodString(e)).append("\n"); + api.add(depth(indent)+"METHOD "+makeMethodString(e)); } return null; }