1.1 --- a/src/share/classes/com/sun/tools/jdeps/Analyzer.java Thu Oct 17 13:50:00 2013 +0200 1.2 +++ b/src/share/classes/com/sun/tools/jdeps/Analyzer.java Thu Oct 17 13:19:48 2013 -0700 1.3 @@ -25,9 +25,8 @@ 1.4 package com.sun.tools.jdeps; 1.5 1.6 import com.sun.tools.classfile.Dependency.Location; 1.7 -import java.util.ArrayList; 1.8 +import com.sun.tools.jdeps.PlatformClassPath.JDKArchive; 1.9 import java.util.HashMap; 1.10 -import java.util.HashSet; 1.11 import java.util.List; 1.12 import java.util.Map; 1.13 import java.util.Set; 1.14 @@ -52,8 +51,8 @@ 1.15 }; 1.16 1.17 private final Type type; 1.18 - private final List<ArchiveDeps> results = new ArrayList<ArchiveDeps>(); 1.19 - private final Map<String, Archive> map = new HashMap<String, Archive>(); 1.20 + private final Map<Archive, ArchiveDeps> results = new HashMap<>(); 1.21 + private final Map<String, Archive> map = new HashMap<>(); 1.22 private final Archive NOT_FOUND 1.23 = new Archive(JdepsTask.getMessage("artifact.not.found")); 1.24 1.25 @@ -78,27 +77,27 @@ 1.26 deps = new PackageVisitor(archive); 1.27 } 1.28 archive.visit(deps); 1.29 - results.add(deps); 1.30 + results.put(archive, deps); 1.31 } 1.32 1.33 // set the required dependencies 1.34 - for (ArchiveDeps result: results) { 1.35 + for (ArchiveDeps result: results.values()) { 1.36 for (Set<String> set : result.deps.values()) { 1.37 for (String target : set) { 1.38 Archive source = getArchive(target); 1.39 if (result.archive != source) { 1.40 - if (!result.requiredArchives.contains(source)) { 1.41 - result.requiredArchives.add(source); 1.42 + String profile = ""; 1.43 + if (source instanceof JDKArchive) { 1.44 + profile = result.profile != null ? result.profile.toString() : ""; 1.45 + if (result.getTargetProfile(target) == null) { 1.46 + profile += ", JDK internal API"; 1.47 + // override the value if it accesses any JDK internal 1.48 + result.requireArchives.put(source, profile); 1.49 + continue; 1.50 + } 1.51 } 1.52 - // either a profile name or the archive name 1.53 - String tname = result.getTargetProfile(target); 1.54 - if (tname.isEmpty()) { 1.55 - tname = PlatformClassPath.contains(source) 1.56 - ? "JDK internal API (" + source.getFileName() + ")" 1.57 - : source.toString(); 1.58 - } 1.59 - if (!result.targetNames.contains(tname)) { 1.60 - result.targetNames.add(tname); 1.61 + if (!result.requireArchives.containsKey(source)) { 1.62 + result.requireArchives.put(source, profile); 1.63 } 1.64 } 1.65 } 1.66 @@ -106,42 +105,46 @@ 1.67 } 1.68 } 1.69 1.70 + public boolean hasDependences(Archive archive) { 1.71 + if (results.containsKey(archive)) { 1.72 + return results.get(archive).deps.size() > 0; 1.73 + } 1.74 + return false; 1.75 + } 1.76 + 1.77 public interface Visitor { 1.78 /** 1.79 + * Visits the source archive to its destination archive of 1.80 + * a recorded dependency. 1.81 + */ 1.82 + void visitArchiveDependence(Archive origin, Archive target, String profile); 1.83 + /** 1.84 * Visits a recorded dependency from origin to target which can be 1.85 * a fully-qualified classname, a package name, a profile or 1.86 * archive name depending on the Analyzer's type. 1.87 */ 1.88 - void visit(String origin, String target, String profile); 1.89 - /** 1.90 - * Visits the source archive to its destination archive of 1.91 - * a recorded dependency. 1.92 - */ 1.93 - void visit(Archive source, Archive dest); 1.94 + void visitDependence(String origin, Archive source, String target, Archive archive, String profile); 1.95 } 1.96 1.97 - public void visitSummary(Visitor v) { 1.98 - for (ArchiveDeps r : results) { 1.99 - for (Archive a : r.requiredArchives) { 1.100 - v.visit(r.archive, a); 1.101 - } 1.102 - for (String name : r.targetNames) { 1.103 - v.visit(r.archive.getFileName(), name, name); 1.104 - } 1.105 + public void visitArchiveDependences(Archive source, Visitor v) { 1.106 + ArchiveDeps r = results.get(source); 1.107 + for (Map.Entry<Archive,String> e : r.requireArchives.entrySet()) { 1.108 + v.visitArchiveDependence(r.archive, e.getKey(), e.getValue()); 1.109 } 1.110 } 1.111 1.112 - public void visit(Visitor v) { 1.113 - for (ArchiveDeps r: results) { 1.114 - for (Archive a : r.requiredArchives) { 1.115 - v.visit(r.archive, a); 1.116 - } 1.117 - for (String origin : r.deps.keySet()) { 1.118 - for (String target : r.deps.get(origin)) { 1.119 - // filter intra-dependency unless in verbose mode 1.120 - if (type == Type.VERBOSE || getArchive(origin) != getArchive(target)) { 1.121 - v.visit(origin, target, r.getTargetProfile(target)); 1.122 - } 1.123 + public void visitDependences(Archive source, Visitor v) { 1.124 + ArchiveDeps r = results.get(source); 1.125 + for (String origin : r.deps.keySet()) { 1.126 + for (String target : r.deps.get(origin)) { 1.127 + Archive archive = getArchive(target); 1.128 + assert source == getArchive(origin); 1.129 + Profile profile = r.getTargetProfile(target); 1.130 + 1.131 + // filter intra-dependency unless in verbose mode 1.132 + if (type == Type.VERBOSE || archive != source) { 1.133 + v.visitDependence(origin, source, target, archive, 1.134 + profile != null ? profile.toString() : ""); 1.135 } 1.136 } 1.137 } 1.138 @@ -151,29 +154,15 @@ 1.139 return map.containsKey(name) ? map.get(name) : NOT_FOUND; 1.140 } 1.141 1.142 - /** 1.143 - * Returns the file name of the archive for non-JRE class or 1.144 - * internal JRE classes. It returns empty string for SE API. 1.145 - */ 1.146 - public String getArchiveName(String target, String profile) { 1.147 - Archive source = getArchive(target); 1.148 - String name = source.getFileName(); 1.149 - if (PlatformClassPath.contains(source)) 1.150 - return profile.isEmpty() ? "JDK internal API (" + name + ")" : ""; 1.151 - return name; 1.152 - } 1.153 - 1.154 private abstract class ArchiveDeps implements Archive.Visitor { 1.155 final Archive archive; 1.156 - final Set<Archive> requiredArchives; 1.157 - final SortedSet<String> targetNames; 1.158 + final Map<Archive,String> requireArchives; 1.159 final SortedMap<String, SortedSet<String>> deps; 1.160 - 1.161 + Profile profile = null; 1.162 ArchiveDeps(Archive archive) { 1.163 this.archive = archive; 1.164 - this.requiredArchives = new HashSet<Archive>(); 1.165 - this.targetNames = new TreeSet<String>(); 1.166 - this.deps = new TreeMap<String, SortedSet<String>>(); 1.167 + this.requireArchives = new HashMap<>(); 1.168 + this.deps = new TreeMap<>(); 1.169 } 1.170 1.171 void add(String loc) { 1.172 @@ -188,17 +177,19 @@ 1.173 void add(String origin, String target) { 1.174 SortedSet<String> set = deps.get(origin); 1.175 if (set == null) { 1.176 - set = new TreeSet<String>(); 1.177 - deps.put(origin, set); 1.178 + deps.put(origin, set = new TreeSet<>()); 1.179 } 1.180 if (!set.contains(target)) { 1.181 set.add(target); 1.182 + // find the corresponding profile 1.183 + Profile p = getTargetProfile(target); 1.184 + if (profile == null || (p != null && profile.profile < p.profile)) { 1.185 + profile = p; 1.186 + } 1.187 } 1.188 } 1.189 - 1.190 public abstract void visit(Location o, Location t); 1.191 - public abstract String getTargetProfile(String target); 1.192 - 1.193 + public abstract Profile getTargetProfile(String target); 1.194 } 1.195 1.196 private class ClassVisitor extends ArchiveDeps { 1.197 @@ -211,9 +202,9 @@ 1.198 public void visit(Location o, Location t) { 1.199 add(o.getClassName(), t.getClassName()); 1.200 } 1.201 - public String getTargetProfile(String target) { 1.202 + public Profile getTargetProfile(String target) { 1.203 int i = target.lastIndexOf('.'); 1.204 - return (i > 0) ? Profiles.getProfileName(target.substring(0, i)) : ""; 1.205 + return (i > 0) ? Profile.getProfile(target.substring(0, i)) : null; 1.206 } 1.207 } 1.208 1.209 @@ -231,8 +222,8 @@ 1.210 String pkg = loc.getPackageName(); 1.211 return pkg.isEmpty() ? "<unnamed>" : pkg; 1.212 } 1.213 - public String getTargetProfile(String target) { 1.214 - return Profiles.getProfileName(target); 1.215 + public Profile getTargetProfile(String target) { 1.216 + return Profile.getProfile(target); 1.217 } 1.218 } 1.219 }