22 * or visit www.oracle.com if you need additional information or have any |
22 * or visit www.oracle.com if you need additional information or have any |
23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 package com.sun.tools.jdeps; |
25 package com.sun.tools.jdeps; |
26 |
26 |
27 import com.sun.tools.classfile.Dependency; |
|
28 import com.sun.tools.classfile.Dependency.Location; |
27 import com.sun.tools.classfile.Dependency.Location; |
29 import java.io.File; |
28 import java.io.File; |
30 import java.util.Comparator; |
|
31 import java.util.HashMap; |
29 import java.util.HashMap; |
32 import java.util.HashSet; |
30 import java.util.HashSet; |
33 import java.util.Map; |
31 import java.util.Map; |
34 import java.util.Set; |
32 import java.util.Set; |
35 import java.util.SortedMap; |
|
36 import java.util.SortedSet; |
|
37 import java.util.TreeMap; |
|
38 import java.util.TreeSet; |
|
39 |
33 |
40 /** |
34 /** |
41 * Represents the source of the class files. |
35 * Represents the source of the class files. |
42 */ |
36 */ |
43 public class Archive { |
37 public class Archive { |
44 private static Map<String,Archive> archiveForClass = new HashMap<String,Archive>(); |
|
45 public static Archive find(Location loc) { |
|
46 return archiveForClass.get(loc.getName()); |
|
47 } |
|
48 |
|
49 private final File file; |
38 private final File file; |
50 private final String filename; |
39 private final String filename; |
51 private final DependencyRecorder recorder; |
|
52 private final ClassFileReader reader; |
40 private final ClassFileReader reader; |
|
41 private final Map<Location, Set<Location>> deps |
|
42 = new HashMap<Location, Set<Location>>(); |
|
43 |
53 public Archive(String name) { |
44 public Archive(String name) { |
54 this.file = null; |
45 this.file = null; |
55 this.filename = name; |
46 this.filename = name; |
56 this.recorder = new DependencyRecorder(); |
|
57 this.reader = null; |
47 this.reader = null; |
58 } |
48 } |
59 |
49 |
60 public Archive(File f, ClassFileReader reader) { |
50 public Archive(File f, ClassFileReader reader) { |
61 this.file = f; |
51 this.file = f; |
62 this.filename = f.getName(); |
52 this.filename = f.getName(); |
63 this.recorder = new DependencyRecorder(); |
|
64 this.reader = reader; |
53 this.reader = reader; |
65 } |
54 } |
66 |
55 |
67 public ClassFileReader reader() { |
56 public ClassFileReader reader() { |
68 return reader; |
57 return reader; |
70 |
59 |
71 public String getFileName() { |
60 public String getFileName() { |
72 return filename; |
61 return filename; |
73 } |
62 } |
74 |
63 |
75 public void addClass(String classFileName) { |
64 public void addClass(Location origin) { |
76 Archive a = archiveForClass.get(classFileName); |
65 Set<Location> set = deps.get(origin); |
77 assert(a == null || a == this); // ## issue warning? |
66 if (set == null) { |
78 if (!archiveForClass.containsKey(classFileName)) { |
67 set = new HashSet<Location>(); |
79 archiveForClass.put(classFileName, this); |
68 deps.put(origin, set); |
80 } |
69 } |
81 } |
70 } |
82 |
71 public void addClass(Location origin, Location target) { |
83 public void addDependency(Dependency d) { |
72 Set<Location> set = deps.get(origin); |
84 recorder.addDependency(d); |
73 if (set == null) { |
|
74 set = new HashSet<Location>(); |
|
75 deps.put(origin, set); |
|
76 } |
|
77 set.add(target); |
85 } |
78 } |
86 |
79 |
87 /** |
80 public void visit(Visitor v) { |
88 * Returns a sorted map of a class to its dependencies. |
81 for (Map.Entry<Location,Set<Location>> e: deps.entrySet()) { |
89 */ |
82 v.visit(e.getKey()); |
90 public SortedMap<Location, SortedSet<Location>> getDependencies() { |
83 for (Location target : e.getValue()) { |
91 DependencyRecorder.Filter filter = new DependencyRecorder.Filter() { |
84 v.visit(e.getKey(), target); |
92 public boolean accept(Location origin, Location target) { |
|
93 return (archiveForClass.get(origin.getName()) != |
|
94 archiveForClass.get(target.getName())); |
|
95 }}; |
|
96 |
|
97 SortedMap<Location, SortedSet<Location>> result = |
|
98 new TreeMap<Location, SortedSet<Location>>(locationComparator); |
|
99 for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) { |
|
100 Location o = e.getKey(); |
|
101 for (Location t : e.getValue()) { |
|
102 if (filter.accept(o, t)) { |
|
103 SortedSet<Location> odeps = result.get(o); |
|
104 if (odeps == null) { |
|
105 odeps = new TreeSet<Location>(locationComparator); |
|
106 result.put(o, odeps); |
|
107 } |
|
108 odeps.add(t); |
|
109 } |
|
110 } |
85 } |
111 } |
86 } |
112 return result; |
|
113 } |
|
114 |
|
115 /** |
|
116 * Returns the set of archives this archive requires. |
|
117 */ |
|
118 public Set<Archive> getRequiredArchives() { |
|
119 SortedSet<Archive> deps = new TreeSet<Archive>(new Comparator<Archive>() { |
|
120 public int compare(Archive a1, Archive a2) { |
|
121 return a1.toString().compareTo(a2.toString()); |
|
122 } |
|
123 }); |
|
124 |
|
125 for (Map.Entry<Location, Set<Location>> e : recorder.dependencies().entrySet()) { |
|
126 Location o = e.getKey(); |
|
127 Archive origin = Archive.find(o); |
|
128 for (Location t : e.getValue()) { |
|
129 Archive target = Archive.find(t); |
|
130 assert(origin != null && target != null); |
|
131 if (origin != target) { |
|
132 if (!deps.contains(target)) { |
|
133 deps.add(target); |
|
134 } |
|
135 } |
|
136 } |
|
137 } |
|
138 return deps; |
|
139 } |
87 } |
140 |
88 |
141 public String toString() { |
89 public String toString() { |
142 return file != null ? file.getPath() : filename; |
90 return file != null ? file.getPath() : filename; |
143 } |
91 } |
144 |
92 |
145 private static class DependencyRecorder { |
93 interface Visitor { |
146 static interface Filter { |
94 void visit(Location loc); |
147 boolean accept(Location origin, Location target); |
95 void visit(Location origin, Location target); |
148 } |
|
149 |
|
150 public void addDependency(Dependency d) { |
|
151 Set<Location> odeps = map.get(d.getOrigin()); |
|
152 if (odeps == null) { |
|
153 odeps = new HashSet<Location>(); |
|
154 map.put(d.getOrigin(), odeps); |
|
155 } |
|
156 odeps.add(d.getTarget()); |
|
157 } |
|
158 |
|
159 public Map<Location, Set<Location>> dependencies() { |
|
160 return map; |
|
161 } |
|
162 |
|
163 private final Map<Location, Set<Location>> map = |
|
164 new HashMap<Location, Set<Location>>(); |
|
165 } |
96 } |
166 |
|
167 private static Comparator<Location> locationComparator = |
|
168 new Comparator<Location>() { |
|
169 public int compare(Location o1, Location o2) { |
|
170 return o1.toString().compareTo(o2.toString()); |
|
171 } |
|
172 }; |
|
173 } |
97 } |