9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.sjavac;
27
28 import java.io.File;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.Map;
32 import java.util.Set;
33
34 import com.sun.tools.javac.util.Assert;
35
36 /**
37 * The build state class captures the source code and generated artifacts
38 * from a build. There are usually two build states, the previous one (prev),
39 * loaded from the javac_state file, and the current one (now).
40 *
41 * <p><b>This is NOT part of any supported API.
42 * If you write code that depends on this, you do so at your own risk.
43 * This code and its internal interfaces are subject to change or
44 * deletion without notice.</b>
45 */
46 public class BuildState {
47 private Map<String,Module> modules = new HashMap<>();
48 private Map<String,Package> packages = new HashMap<>();
49 private Map<String,Source> sources = new HashMap<>();
50 private Map<String,File> artifacts = new HashMap<>();
51 // Map from package to a set of packages that depend on said package.
52 private Map<String,Set<String>> dependents = new HashMap<>();
53
54 public Map<String,Module> modules() { return modules; }
60 /**
61 * Lookup a module from a name. Create the module if it does
62 * not exist yet.
63 */
64 public Module lookupModule(String mod) {
65 Module m = modules.get(mod);
66 if (m == null) {
67 m = new Module(mod, "???");
68 modules.put(mod, m);
69 }
70 return m;
71 }
72
73 /**
74 * Find a module from a given package name. For example:
75 * The package name "base:java.lang" will fetch the module named "base".
76 * The package name ":java.net" will fetch the default module.
77 */
78 Module findModuleFromPackageName(String pkg) {
79 int cp = pkg.indexOf(':');
80 Assert.check(cp != -1);
81 String mod = pkg.substring(0, cp);
82 return lookupModule(mod);
83 }
84
85 /**
86 * Store references to all packages, sources and artifacts for all modules
87 * into the build state. I.e. flatten the module tree structure
88 * into global maps stored in the BuildState for easy access.
89 *
90 * @param m The set of modules.
91 */
92 public void flattenPackagesSourcesAndArtifacts(Map<String,Module> m) {
93 modules = m;
94 // Extract all the found packages.
95 for (Module i : modules.values()) {
96 for (Map.Entry<String,Package> j : i.packages().entrySet()) {
97 Package p = packages.get(j.getKey());
98 // Check that no two different packages are stored under same name.
99 Assert.check(p == null || p == j.getValue());
100 if (p == null) {
137 Package p = packages.get(j.getKey());
138 // Check that no two different packages are stored under same name.
139 Assert.check(p == null || p == j.getValue());
140 p = j.getValue();
141 packages.put(j.getKey(),j.getValue());
142 for (Map.Entry<String,File> g : p.artifacts().entrySet()) {
143 File f = artifacts.get(g.getKey());
144 // Check that no two artifacts are stored under the same file.
145 Assert.check(f == null || f == g.getValue());
146 artifacts.put(g.getKey(), g.getValue());
147 }
148 }
149 }
150 }
151
152 /**
153 * Calculate the package dependents (ie the reverse of the dependencies).
154 */
155 public void calculateDependents() {
156 dependents = new HashMap<>();
157 for (String s : packages.keySet()) {
158 Package p = packages.get(s);
159 for (String d : p.dependencies()) {
160 Set<String> ss = dependents.get(d);
161 if (ss == null) {
162 ss = new HashSet<>();
163 dependents.put(d, ss);
164 }
165 // Add the dependent information to the global dependent map.
166 ss.add(s);
167 Package dp = packages.get(d);
168 // Also add the dependent information to the package specific map.
169 // Normally, you do not compile java.lang et al. Therefore
170 // there are several packages that p depends upon that you
171 // do not have in your state database. This is perfectly fine.
172 if (dp != null) {
173 // But this package did exist in the state database.
174 dp.addDependent(p.name());
175 }
176 }
177 }
178 }
179
180 /**
181 * Verify that the setModules method above did the right thing when
182 * running through the module->package->source structure.
183 */
184 public void checkInternalState(String msg, boolean linkedOnly, Map<String,Source> srcs) {
185 boolean baad = false;
186 Map<String,Source> original = new HashMap<>();
187 Map<String,Source> calculated = new HashMap<>();
188
189 for (String s : sources.keySet()) {
190 Source ss = sources.get(s);
191 if (ss.isLinkedOnly() == linkedOnly) {
253 return p;
254 }
255
256 /**
257 * Load a source from the javac state file.
258 */
259 public Source loadSource(Package lastPackage, String l, boolean is_generated) {
260 Source s = Source.load(lastPackage, l, is_generated);
261 lastPackage.addSource(s);
262 sources.put(s.name(), s);
263 return s;
264 }
265
266 /**
267 * During an incremental compile we need to copy the old javac state
268 * information about packages that were not recompiled.
269 */
270 public void copyPackagesExcept(BuildState prev, Set<String> recompiled, Set<String> removed) {
271 for (String pkg : prev.packages().keySet()) {
272 // Do not copy recompiled or removed packages.
273 if (recompiled.contains(pkg) || removed.contains(pkg)) continue;
274 Module mnew = findModuleFromPackageName(pkg);
275 Package pprev = prev.packages().get(pkg);
276 mnew.addPackage(pprev);
277 // Do not forget to update the flattened data.
278 packages.put(pkg, pprev);
279 }
280 }
281 }
|
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package com.sun.tools.sjavac;
27
28 import java.io.File;
29 import java.util.Collections;
30 import java.util.HashMap;
31 import java.util.Map;
32 import java.util.Set;
33
34 import com.sun.tools.javac.util.Assert;
35 import com.sun.tools.sjavac.pubapi.PubApi;
36
37 /**
38 * The build state class captures the source code and generated artifacts
39 * from a build. There are usually two build states, the previous one (prev),
40 * loaded from the javac_state file, and the current one (now).
41 *
42 * <p><b>This is NOT part of any supported API.
43 * If you write code that depends on this, you do so at your own risk.
44 * This code and its internal interfaces are subject to change or
45 * deletion without notice.</b>
46 */
47 public class BuildState {
48 private Map<String,Module> modules = new HashMap<>();
49 private Map<String,Package> packages = new HashMap<>();
50 private Map<String,Source> sources = new HashMap<>();
51 private Map<String,File> artifacts = new HashMap<>();
52 // Map from package to a set of packages that depend on said package.
53 private Map<String,Set<String>> dependents = new HashMap<>();
54
55 public Map<String,Module> modules() { return modules; }
61 /**
62 * Lookup a module from a name. Create the module if it does
63 * not exist yet.
64 */
65 public Module lookupModule(String mod) {
66 Module m = modules.get(mod);
67 if (m == null) {
68 m = new Module(mod, "???");
69 modules.put(mod, m);
70 }
71 return m;
72 }
73
74 /**
75 * Find a module from a given package name. For example:
76 * The package name "base:java.lang" will fetch the module named "base".
77 * The package name ":java.net" will fetch the default module.
78 */
79 Module findModuleFromPackageName(String pkg) {
80 int cp = pkg.indexOf(':');
81 Assert.check(cp != -1, "Could not find package name");
82 String mod = pkg.substring(0, cp);
83 return lookupModule(mod);
84 }
85
86 /**
87 * Store references to all packages, sources and artifacts for all modules
88 * into the build state. I.e. flatten the module tree structure
89 * into global maps stored in the BuildState for easy access.
90 *
91 * @param m The set of modules.
92 */
93 public void flattenPackagesSourcesAndArtifacts(Map<String,Module> m) {
94 modules = m;
95 // Extract all the found packages.
96 for (Module i : modules.values()) {
97 for (Map.Entry<String,Package> j : i.packages().entrySet()) {
98 Package p = packages.get(j.getKey());
99 // Check that no two different packages are stored under same name.
100 Assert.check(p == null || p == j.getValue());
101 if (p == null) {
138 Package p = packages.get(j.getKey());
139 // Check that no two different packages are stored under same name.
140 Assert.check(p == null || p == j.getValue());
141 p = j.getValue();
142 packages.put(j.getKey(),j.getValue());
143 for (Map.Entry<String,File> g : p.artifacts().entrySet()) {
144 File f = artifacts.get(g.getKey());
145 // Check that no two artifacts are stored under the same file.
146 Assert.check(f == null || f == g.getValue());
147 artifacts.put(g.getKey(), g.getValue());
148 }
149 }
150 }
151 }
152
153 /**
154 * Calculate the package dependents (ie the reverse of the dependencies).
155 */
156 public void calculateDependents() {
157 dependents = new HashMap<>();
158
159 for (String s : packages.keySet()) {
160 Package p = packages.get(s);
161
162 // Collect all dependencies of the classes in this package
163 Set<String> deps = p.typeDependencies() // maps fqName -> set of dependencies
164 .values()
165 .stream()
166 .reduce(Collections.emptySet(), Util::union);
167
168 // Now reverse the direction
169
170 for (String dep : deps) {
171 // Add the dependent information to the global dependent map.
172 String depPkgStr = ":" + dep.substring(0, dep.lastIndexOf('.'));
173 dependents.merge(depPkgStr, Collections.singleton(s), Util::union);
174
175 // Also add the dependent information to the package specific map.
176 // Normally, you do not compile java.lang et al. Therefore
177 // there are several packages that p depends upon that you
178 // do not have in your state database. This is perfectly fine.
179 Package dp = packages.get(depPkgStr);
180 if (dp != null) {
181 // But this package did exist in the state database.
182 dp.addDependent(p.name());
183 }
184 }
185 }
186 }
187
188 /**
189 * Verify that the setModules method above did the right thing when
190 * running through the module->package->source structure.
191 */
192 public void checkInternalState(String msg, boolean linkedOnly, Map<String,Source> srcs) {
193 boolean baad = false;
194 Map<String,Source> original = new HashMap<>();
195 Map<String,Source> calculated = new HashMap<>();
196
197 for (String s : sources.keySet()) {
198 Source ss = sources.get(s);
199 if (ss.isLinkedOnly() == linkedOnly) {
261 return p;
262 }
263
264 /**
265 * Load a source from the javac state file.
266 */
267 public Source loadSource(Package lastPackage, String l, boolean is_generated) {
268 Source s = Source.load(lastPackage, l, is_generated);
269 lastPackage.addSource(s);
270 sources.put(s.name(), s);
271 return s;
272 }
273
274 /**
275 * During an incremental compile we need to copy the old javac state
276 * information about packages that were not recompiled.
277 */
278 public void copyPackagesExcept(BuildState prev, Set<String> recompiled, Set<String> removed) {
279 for (String pkg : prev.packages().keySet()) {
280 // Do not copy recompiled or removed packages.
281 if (recompiled.contains(pkg) || removed.contains(pkg))
282 continue;
283
284 Module mnew = findModuleFromPackageName(pkg);
285 Package pprev = prev.packages().get(pkg);
286
287 // Even though we haven't recompiled this package, we may have
288 // information about its public API: It may be a classpath dependency
289 if (packages.containsKey(pkg)) {
290 pprev.setPubapi(PubApi.mergeTypes(pprev.getPubApi(),
291 packages.get(pkg).getPubApi()));
292 }
293
294 mnew.addPackage(pprev);
295 // Do not forget to update the flattened data. (See JDK-8071904)
296 packages.put(pkg, pprev);
297 }
298 }
299 }
|