76 deps = new ClassVisitor(archive); |
75 deps = new ClassVisitor(archive); |
77 } else { |
76 } else { |
78 deps = new PackageVisitor(archive); |
77 deps = new PackageVisitor(archive); |
79 } |
78 } |
80 archive.visit(deps); |
79 archive.visit(deps); |
81 results.add(deps); |
80 results.put(archive, deps); |
82 } |
81 } |
83 |
82 |
84 // set the required dependencies |
83 // set the required dependencies |
85 for (ArchiveDeps result: results) { |
84 for (ArchiveDeps result: results.values()) { |
86 for (Set<String> set : result.deps.values()) { |
85 for (Set<String> set : result.deps.values()) { |
87 for (String target : set) { |
86 for (String target : set) { |
88 Archive source = getArchive(target); |
87 Archive source = getArchive(target); |
89 if (result.archive != source) { |
88 if (result.archive != source) { |
90 if (!result.requiredArchives.contains(source)) { |
89 String profile = ""; |
91 result.requiredArchives.add(source); |
90 if (source instanceof JDKArchive) { |
|
91 profile = result.profile != null ? result.profile.toString() : ""; |
|
92 if (result.getTargetProfile(target) == null) { |
|
93 profile += ", JDK internal API"; |
|
94 // override the value if it accesses any JDK internal |
|
95 result.requireArchives.put(source, profile); |
|
96 continue; |
|
97 } |
92 } |
98 } |
93 // either a profile name or the archive name |
99 if (!result.requireArchives.containsKey(source)) { |
94 String tname = result.getTargetProfile(target); |
100 result.requireArchives.put(source, profile); |
95 if (tname.isEmpty()) { |
|
96 tname = PlatformClassPath.contains(source) |
|
97 ? "JDK internal API (" + source.getFileName() + ")" |
|
98 : source.toString(); |
|
99 } |
|
100 if (!result.targetNames.contains(tname)) { |
|
101 result.targetNames.add(tname); |
|
102 } |
101 } |
103 } |
102 } |
104 } |
103 } |
105 } |
104 } |
106 } |
105 } |
107 } |
106 } |
108 |
107 |
|
108 public boolean hasDependences(Archive archive) { |
|
109 if (results.containsKey(archive)) { |
|
110 return results.get(archive).deps.size() > 0; |
|
111 } |
|
112 return false; |
|
113 } |
|
114 |
109 public interface Visitor { |
115 public interface Visitor { |
|
116 /** |
|
117 * Visits the source archive to its destination archive of |
|
118 * a recorded dependency. |
|
119 */ |
|
120 void visitArchiveDependence(Archive origin, Archive target, String profile); |
110 /** |
121 /** |
111 * Visits a recorded dependency from origin to target which can be |
122 * Visits a recorded dependency from origin to target which can be |
112 * a fully-qualified classname, a package name, a profile or |
123 * a fully-qualified classname, a package name, a profile or |
113 * archive name depending on the Analyzer's type. |
124 * archive name depending on the Analyzer's type. |
114 */ |
125 */ |
115 void visit(String origin, String target, String profile); |
126 void visitDependence(String origin, Archive source, String target, Archive archive, String profile); |
116 /** |
127 } |
117 * Visits the source archive to its destination archive of |
128 |
118 * a recorded dependency. |
129 public void visitArchiveDependences(Archive source, Visitor v) { |
119 */ |
130 ArchiveDeps r = results.get(source); |
120 void visit(Archive source, Archive dest); |
131 for (Map.Entry<Archive,String> e : r.requireArchives.entrySet()) { |
121 } |
132 v.visitArchiveDependence(r.archive, e.getKey(), e.getValue()); |
122 |
133 } |
123 public void visitSummary(Visitor v) { |
134 } |
124 for (ArchiveDeps r : results) { |
135 |
125 for (Archive a : r.requiredArchives) { |
136 public void visitDependences(Archive source, Visitor v) { |
126 v.visit(r.archive, a); |
137 ArchiveDeps r = results.get(source); |
127 } |
138 for (String origin : r.deps.keySet()) { |
128 for (String name : r.targetNames) { |
139 for (String target : r.deps.get(origin)) { |
129 v.visit(r.archive.getFileName(), name, name); |
140 Archive archive = getArchive(target); |
130 } |
141 assert source == getArchive(origin); |
131 } |
142 Profile profile = r.getTargetProfile(target); |
132 } |
143 |
133 |
144 // filter intra-dependency unless in verbose mode |
134 public void visit(Visitor v) { |
145 if (type == Type.VERBOSE || archive != source) { |
135 for (ArchiveDeps r: results) { |
146 v.visitDependence(origin, source, target, archive, |
136 for (Archive a : r.requiredArchives) { |
147 profile != null ? profile.toString() : ""); |
137 v.visit(r.archive, a); |
|
138 } |
|
139 for (String origin : r.deps.keySet()) { |
|
140 for (String target : r.deps.get(origin)) { |
|
141 // filter intra-dependency unless in verbose mode |
|
142 if (type == Type.VERBOSE || getArchive(origin) != getArchive(target)) { |
|
143 v.visit(origin, target, r.getTargetProfile(target)); |
|
144 } |
|
145 } |
148 } |
146 } |
149 } |
147 } |
150 } |
148 } |
151 } |
149 |
152 |
150 public Archive getArchive(String name) { |
153 public Archive getArchive(String name) { |
151 return map.containsKey(name) ? map.get(name) : NOT_FOUND; |
154 return map.containsKey(name) ? map.get(name) : NOT_FOUND; |
152 } |
155 } |
153 |
156 |
154 /** |
|
155 * Returns the file name of the archive for non-JRE class or |
|
156 * internal JRE classes. It returns empty string for SE API. |
|
157 */ |
|
158 public String getArchiveName(String target, String profile) { |
|
159 Archive source = getArchive(target); |
|
160 String name = source.getFileName(); |
|
161 if (PlatformClassPath.contains(source)) |
|
162 return profile.isEmpty() ? "JDK internal API (" + name + ")" : ""; |
|
163 return name; |
|
164 } |
|
165 |
|
166 private abstract class ArchiveDeps implements Archive.Visitor { |
157 private abstract class ArchiveDeps implements Archive.Visitor { |
167 final Archive archive; |
158 final Archive archive; |
168 final Set<Archive> requiredArchives; |
159 final Map<Archive,String> requireArchives; |
169 final SortedSet<String> targetNames; |
|
170 final SortedMap<String, SortedSet<String>> deps; |
160 final SortedMap<String, SortedSet<String>> deps; |
171 |
161 Profile profile = null; |
172 ArchiveDeps(Archive archive) { |
162 ArchiveDeps(Archive archive) { |
173 this.archive = archive; |
163 this.archive = archive; |
174 this.requiredArchives = new HashSet<Archive>(); |
164 this.requireArchives = new HashMap<>(); |
175 this.targetNames = new TreeSet<String>(); |
165 this.deps = new TreeMap<>(); |
176 this.deps = new TreeMap<String, SortedSet<String>>(); |
|
177 } |
166 } |
178 |
167 |
179 void add(String loc) { |
168 void add(String loc) { |
180 Archive a = map.get(loc); |
169 Archive a = map.get(loc); |
181 if (a == null) { |
170 if (a == null) { |