src/share/classes/com/sun/tools/sjavac/Package.java

Mon, 11 Mar 2013 19:03:35 -0700

author
ohrstrom
date
Mon, 11 Mar 2013 19:03:35 -0700
changeset 1625
fbb6e470079d
parent 1504
22e417cdddee
child 2227
998b10c43157
permissions
-rw-r--r--

8009843: sjavac should accept -cp as synonym for -classpath
Reviewed-by: jjg

ohrstrom@1504 1 /*
ohrstrom@1504 2 * Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
ohrstrom@1504 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
ohrstrom@1504 4 *
ohrstrom@1504 5 * This code is free software; you can redistribute it and/or modify it
ohrstrom@1504 6 * under the terms of the GNU General Public License version 2 only, as
ohrstrom@1504 7 * published by the Free Software Foundation. Oracle designates this
ohrstrom@1504 8 * particular file as subject to the "Classpath" exception as provided
ohrstrom@1504 9 * by Oracle in the LICENSE file that accompanied this code.
ohrstrom@1504 10 *
ohrstrom@1504 11 * This code is distributed in the hope that it will be useful, but WITHOUT
ohrstrom@1504 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
ohrstrom@1504 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
ohrstrom@1504 14 * version 2 for more details (a copy is included in the LICENSE file that
ohrstrom@1504 15 * accompanied this code).
ohrstrom@1504 16 *
ohrstrom@1504 17 * You should have received a copy of the GNU General Public License version
ohrstrom@1504 18 * 2 along with this work; if not, write to the Free Software Foundation,
ohrstrom@1504 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
ohrstrom@1504 20 *
ohrstrom@1504 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
ohrstrom@1504 22 * or visit www.oracle.com if you need additional information or have any
ohrstrom@1504 23 * questions.
ohrstrom@1504 24 */
ohrstrom@1504 25
ohrstrom@1504 26 package com.sun.tools.sjavac;
ohrstrom@1504 27
ohrstrom@1504 28 import java.io.File;
ohrstrom@1504 29 import java.net.URI;
ohrstrom@1504 30 import java.util.ArrayList;
ohrstrom@1504 31 import java.util.Collections;
ohrstrom@1504 32 import java.util.HashMap;
ohrstrom@1504 33 import java.util.HashSet;
ohrstrom@1504 34 import java.util.Iterator;
ohrstrom@1504 35 import java.util.List;
ohrstrom@1504 36 import java.util.Map;
ohrstrom@1504 37 import java.util.Set;
ohrstrom@1504 38
ohrstrom@1504 39 /**
ohrstrom@1504 40 * The Package class maintains meta information about a package.
ohrstrom@1504 41 * For example its sources, dependents,its pubapi and its artifacts.
ohrstrom@1504 42 *
ohrstrom@1504 43 * It might look odd that we track dependents/pubapi/artifacts on
ohrstrom@1504 44 * a package level, but it makes sense since recompiling a full package
ohrstrom@1504 45 * takes as long as recompiling a single java file in that package,
ohrstrom@1504 46 * if you take into account the startup time of the jvm.
ohrstrom@1504 47 *
ohrstrom@1504 48 * Also the dependency information will be much smaller (good for the javac_state file size)
ohrstrom@1504 49 * and it simplifies tracking artifact generation, you do not always know from which
ohrstrom@1504 50 * source a class file was generated, but you always know which package it belongs to.
ohrstrom@1504 51 *
ohrstrom@1504 52 * It is also educational to see package dependencies triggering recompilation of
ohrstrom@1504 53 * other packages. Even though the recompilation was perhaps not necessary,
ohrstrom@1504 54 * the visible recompilation of the dependent packages indicates how much circular
ohrstrom@1504 55 * dependencies your code has.
ohrstrom@1504 56 *
ohrstrom@1504 57 * <p><b>This is NOT part of any supported API.
ohrstrom@1504 58 * If you write code that depends on this, you do so at your own
ohrstrom@1504 59 * risk. This code and its internal interfaces are subject to change
ohrstrom@1504 60 * or deletion without notice.</b></p>
ohrstrom@1504 61 */
ohrstrom@1504 62 public class Package implements Comparable<Package> {
ohrstrom@1504 63 // The module this package belongs to. (There is a legacy module with an empty string name,
ohrstrom@1504 64 // used for all legacy sources.)
ohrstrom@1504 65 private Module mod;
ohrstrom@1504 66 // Name of this package, module:pkg
ohrstrom@1504 67 // ex1 jdk.base:java.lang
ohrstrom@1504 68 // ex2 :java.lang (when in legacy mode)
ohrstrom@1504 69 private String name;
ohrstrom@1504 70 // The directory path to the package. If the package belongs to a module,
ohrstrom@1504 71 // then that module's file system name is part of the path.
ohrstrom@1504 72 private String dirname;
ohrstrom@1504 73 // This package depends on these packages.
ohrstrom@1504 74 private Set<String> dependencies = new HashSet<String>();
ohrstrom@1504 75 // This package has the following dependents, that depend on this package.
ohrstrom@1504 76 private Set<String> dependents = new HashSet<String>();
ohrstrom@1504 77 // This is the public api of this package.
ohrstrom@1504 78 private List<String> pubapi = new ArrayList<String>();
ohrstrom@1504 79 // Map from source file name to Source info object.
ohrstrom@1504 80 private Map<String,Source> sources = new HashMap<String,Source>();
ohrstrom@1504 81 // This package generated these artifacts.
ohrstrom@1504 82 private Map<String,File> artifacts = new HashMap<String,File>();
ohrstrom@1504 83
ohrstrom@1504 84 public Package(Module m, String n) {
ohrstrom@1504 85 int c = n.indexOf(":");
ohrstrom@1504 86 assert(c != -1);
ohrstrom@1504 87 String mn = n.substring(0,c);
ohrstrom@1504 88 assert(m.name().equals(m.name()));
ohrstrom@1504 89 name = n;
ohrstrom@1504 90 dirname = n.replace('.', File.separatorChar);
ohrstrom@1504 91 if (m.name().length() > 0) {
ohrstrom@1504 92 // There is a module here, prefix the module dir name to the path.
ohrstrom@1504 93 dirname = m.dirname()+File.separatorChar+dirname;
ohrstrom@1504 94 }
ohrstrom@1504 95 }
ohrstrom@1504 96
ohrstrom@1504 97 public Module mod() { return mod; }
ohrstrom@1504 98 public String name() { return name; }
ohrstrom@1504 99 public String dirname() { return dirname; }
ohrstrom@1504 100 public Map<String,Source> sources() { return sources; }
ohrstrom@1504 101 public Map<String,File> artifacts() { return artifacts; }
ohrstrom@1504 102 public List<String> pubapi() { return pubapi; }
ohrstrom@1504 103
ohrstrom@1504 104 public Set<String> dependencies() { return dependencies; }
ohrstrom@1504 105 public Set<String> dependents() { return dependents; }
ohrstrom@1504 106
ohrstrom@1504 107 @Override
ohrstrom@1504 108 public boolean equals(Object o) {
ohrstrom@1504 109 return (o instanceof Package) && name.equals(((Package)o).name);
ohrstrom@1504 110 }
ohrstrom@1504 111
ohrstrom@1504 112 @Override
ohrstrom@1504 113 public int hashCode() {
ohrstrom@1504 114 return name.hashCode();
ohrstrom@1504 115 }
ohrstrom@1504 116
ohrstrom@1504 117 @Override
ohrstrom@1504 118 public int compareTo(Package o) {
ohrstrom@1504 119 return name.compareTo(o.name);
ohrstrom@1504 120 }
ohrstrom@1504 121
ohrstrom@1504 122 public void addSource(Source s) {
ohrstrom@1504 123 sources.put(s.file().getPath(), s);
ohrstrom@1504 124 }
ohrstrom@1504 125
ohrstrom@1504 126 public void addDependency(String d) {
ohrstrom@1504 127 dependencies.add(d);
ohrstrom@1504 128 }
ohrstrom@1504 129
ohrstrom@1504 130 public void addDependent(String d) {
ohrstrom@1504 131 dependents.add(d);
ohrstrom@1504 132 }
ohrstrom@1504 133
ohrstrom@1504 134 public void addPubapi(String p) {
ohrstrom@1504 135 pubapi.add(p);
ohrstrom@1504 136 }
ohrstrom@1504 137
ohrstrom@1504 138 /**
ohrstrom@1504 139 * Check if we have knowledge in the javac state that
ohrstrom@1504 140 * describe the results of compiling this package before.
ohrstrom@1504 141 */
ohrstrom@1504 142 public boolean existsInJavacState() {
ohrstrom@1504 143 return artifacts.size() > 0 || pubapi.size() > 0;
ohrstrom@1504 144 }
ohrstrom@1504 145
ohrstrom@1504 146 public static List<String> pubapiToList(String ps)
ohrstrom@1504 147 {
ohrstrom@1504 148 String[] lines = ps.split("\n");
ohrstrom@1504 149 List<String> r = new ArrayList<String>();
ohrstrom@1504 150 for (String l : lines) {
ohrstrom@1504 151 r.add(l);
ohrstrom@1504 152 }
ohrstrom@1504 153 return r;
ohrstrom@1504 154 }
ohrstrom@1504 155
ohrstrom@1504 156 public boolean hasPubapiChanged(List<String> ps) {
ohrstrom@1504 157 Iterator<String> i = ps.iterator();
ohrstrom@1504 158 Iterator<String> j = pubapi.iterator();
ohrstrom@1504 159 int line = 0;
ohrstrom@1504 160 while (i.hasNext() && j.hasNext()) {
ohrstrom@1504 161 String is = i.next();
ohrstrom@1504 162 String js = j.next();
ohrstrom@1504 163 if (!is.equals(js)) {
ohrstrom@1504 164 Log.debug("Change in pubapi for package "+name+" line "+line);
ohrstrom@1504 165 Log.debug("Old: "+js);
ohrstrom@1504 166 Log.debug("New: "+is);
ohrstrom@1504 167 return true;
ohrstrom@1504 168 }
ohrstrom@1504 169 line++;
ohrstrom@1504 170 }
ohrstrom@1504 171 if ((i.hasNext() && !j.hasNext() ) ||
ohrstrom@1504 172 (!i.hasNext() && j.hasNext())) {
ohrstrom@1504 173 Log.debug("Change in pubapi for package "+name);
ohrstrom@1504 174 if (i.hasNext()) {
ohrstrom@1504 175 Log.debug("New has more lines!");
ohrstrom@1504 176 } else {
ohrstrom@1504 177 Log.debug("Old has more lines!");
ohrstrom@1504 178 }
ohrstrom@1504 179 return true;
ohrstrom@1504 180 }
ohrstrom@1504 181 return false;
ohrstrom@1504 182 }
ohrstrom@1504 183
ohrstrom@1504 184 public void setPubapi(List<String> ps) {
ohrstrom@1504 185 pubapi = ps;
ohrstrom@1504 186 }
ohrstrom@1504 187
ohrstrom@1504 188 public void setDependencies(Set<String> ds) {
ohrstrom@1504 189 dependencies = ds;
ohrstrom@1504 190 }
ohrstrom@1504 191
ohrstrom@1504 192 public void save(StringBuilder b) {
ohrstrom@1504 193 b.append("P ").append(name).append("\n");
ohrstrom@1504 194 Source.saveSources(sources, b);
ohrstrom@1504 195 saveDependencies(b);
ohrstrom@1504 196 savePubapi(b);
ohrstrom@1504 197 saveArtifacts(b);
ohrstrom@1504 198 }
ohrstrom@1504 199
ohrstrom@1504 200 static public Package load(Module module, String l) {
ohrstrom@1504 201 String name = l.substring(2);
ohrstrom@1504 202 return new Package(module, name);
ohrstrom@1504 203 }
ohrstrom@1504 204
ohrstrom@1504 205 public void loadDependency(String l) {
ohrstrom@1504 206 String n = l.substring(2);
ohrstrom@1504 207 addDependency(n);
ohrstrom@1504 208 }
ohrstrom@1504 209
ohrstrom@1504 210 public void loadPubapi(String l) {
ohrstrom@1504 211 String pi = l.substring(2);
ohrstrom@1504 212 addPubapi(pi);
ohrstrom@1504 213 }
ohrstrom@1504 214
ohrstrom@1504 215 public void saveDependencies(StringBuilder b) {
ohrstrom@1504 216 List<String> sorted_dependencies = new ArrayList<String>();
ohrstrom@1504 217 for (String key : dependencies) {
ohrstrom@1504 218 sorted_dependencies.add(key);
ohrstrom@1504 219 }
ohrstrom@1504 220 Collections.sort(sorted_dependencies);
ohrstrom@1504 221 for (String a : sorted_dependencies) {
ohrstrom@1504 222 b.append("D "+a+"\n");
ohrstrom@1504 223 }
ohrstrom@1504 224 }
ohrstrom@1504 225
ohrstrom@1504 226 public void savePubapi(StringBuilder b) {
ohrstrom@1504 227 for (String l : pubapi) {
ohrstrom@1504 228 b.append("I "+l+"\n");
ohrstrom@1504 229 }
ohrstrom@1504 230 }
ohrstrom@1504 231
ohrstrom@1504 232 public static void savePackages(Map<String,Package> packages, StringBuilder b) {
ohrstrom@1504 233 List<String> sorted_packages = new ArrayList<String>();
ohrstrom@1504 234 for (String key : packages.keySet() ) {
ohrstrom@1504 235 sorted_packages.add(key);
ohrstrom@1504 236 }
ohrstrom@1504 237 Collections.sort(sorted_packages);
ohrstrom@1504 238 for (String s : sorted_packages) {
ohrstrom@1504 239 Package p = packages.get(s);
ohrstrom@1504 240 p.save(b);
ohrstrom@1504 241 }
ohrstrom@1504 242 }
ohrstrom@1504 243
ohrstrom@1504 244 public void addArtifact(String a) {
ohrstrom@1504 245 artifacts.put(a, new File(a));
ohrstrom@1504 246 }
ohrstrom@1504 247
ohrstrom@1504 248 public void addArtifact(File f) {
ohrstrom@1504 249 artifacts.put(f.getPath(), f);
ohrstrom@1504 250 }
ohrstrom@1504 251
ohrstrom@1504 252 public void addArtifacts(Set<URI> as) {
ohrstrom@1504 253 for (URI u : as) {
ohrstrom@1504 254 addArtifact(new File(u));
ohrstrom@1504 255 }
ohrstrom@1504 256 }
ohrstrom@1504 257
ohrstrom@1504 258 public void setArtifacts(Set<URI> as) {
ohrstrom@1504 259 assert(!artifacts.isEmpty());
ohrstrom@1504 260 artifacts = new HashMap<String,File>();
ohrstrom@1504 261 addArtifacts(as);
ohrstrom@1504 262 }
ohrstrom@1504 263
ohrstrom@1504 264 public void loadArtifact(String l) {
ohrstrom@1504 265 // Find next space after "A ".
ohrstrom@1504 266 int dp = l.indexOf(' ',2);
ohrstrom@1504 267 String fn = l.substring(2,dp);
ohrstrom@1504 268 long last_modified = Long.parseLong(l.substring(dp+1));
ohrstrom@1504 269 File f = new File(fn);
ohrstrom@1504 270 if (f.exists() && f.lastModified() != last_modified) {
ohrstrom@1504 271 // Hmm, the artifact on disk does not have the same last modified
ohrstrom@1504 272 // timestamp as the information from the build database.
ohrstrom@1504 273 // We no longer trust the artifact on disk. Delete it.
ohrstrom@1504 274 // The smart javac wrapper will then rebuild the artifact.
ohrstrom@1504 275 Log.debug("Removing "+f.getPath()+" since its timestamp does not match javac_state.");
ohrstrom@1504 276 f.delete();
ohrstrom@1504 277 }
ohrstrom@1504 278 artifacts.put(f.getPath(), f);
ohrstrom@1504 279 }
ohrstrom@1504 280
ohrstrom@1504 281 public void saveArtifacts(StringBuilder b) {
ohrstrom@1504 282 List<File> sorted_artifacts = new ArrayList<File>();
ohrstrom@1504 283 for (File f : artifacts.values()) {
ohrstrom@1504 284 sorted_artifacts.add(f);
ohrstrom@1504 285 }
ohrstrom@1504 286 Collections.sort(sorted_artifacts);
ohrstrom@1504 287 for (File f : sorted_artifacts) {
ohrstrom@1504 288 // The last modified information is only used
ohrstrom@1504 289 // to detect tampering with the output dir.
ohrstrom@1504 290 // If the outputdir has been modified, not by javac,
ohrstrom@1504 291 // then a mismatch will be detected in the last modified
ohrstrom@1504 292 // timestamps stored in the build database compared
ohrstrom@1504 293 // to the timestamps on disk and the artifact will be deleted.
ohrstrom@1504 294
ohrstrom@1504 295 b.append("A "+f.getPath()+" "+f.lastModified()+"\n");
ohrstrom@1504 296 }
ohrstrom@1504 297 }
ohrstrom@1504 298
ohrstrom@1504 299 /**
ohrstrom@1504 300 * Always clean out a tainted package before it is recompiled.
ohrstrom@1504 301 */
ohrstrom@1504 302 public void deleteArtifacts() {
ohrstrom@1504 303 for (File a : artifacts.values()) {
ohrstrom@1504 304 a.delete();
ohrstrom@1504 305 }
ohrstrom@1504 306 }
ohrstrom@1504 307 }

mercurial