src/share/classes/com/sun/tools/sjavac/Source.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.util.Set;
ohrstrom@1504 30 import java.util.Collections;
ohrstrom@1504 31 import java.util.List;
ohrstrom@1504 32 import java.util.ArrayList;
ohrstrom@1504 33 import java.util.Map;
ohrstrom@1504 34
ohrstrom@1504 35 /** A Source object maintains information about a source file.
ohrstrom@1504 36 * For example which package it belongs to and kind of source it is.
ohrstrom@1504 37 * The class also knows how to find source files (scanRoot) given include/exclude
ohrstrom@1504 38 * patterns and a root.
ohrstrom@1504 39 *
ohrstrom@1504 40 * <p><b>This is NOT part of any supported API.
ohrstrom@1504 41 * If you write code that depends on this, you do so at your own
ohrstrom@1504 42 * risk. This code and its internal interfaces are subject to change
ohrstrom@1504 43 * or deletion without notice.</b></p>
ohrstrom@1504 44 */
ohrstrom@1504 45 public class Source implements Comparable<Source> {
ohrstrom@1504 46 // The package the source belongs to.
ohrstrom@1504 47 private Package pkg;
ohrstrom@1504 48 // Name of this source file, relative its source root.
ohrstrom@1504 49 // For example: java/lang/Object.java
ohrstrom@1504 50 // Or if the source file is inside a module:
ohrstrom@1504 51 // jdk.base/java/lang/Object.java
ohrstrom@1504 52 private String name;
ohrstrom@1504 53 // What kind of file is this.
ohrstrom@1504 54 private String suffix;
ohrstrom@1504 55 // When this source file was last_modified
ohrstrom@1504 56 private long lastModified;
ohrstrom@1504 57 // The source File.
ohrstrom@1504 58 private File file;
ohrstrom@1504 59 // The source root under which file resides.
ohrstrom@1504 60 private File root;
ohrstrom@1504 61 // If the source is generated.
ohrstrom@1504 62 private boolean isGenerated;
ohrstrom@1504 63 // If the source is only linked to, not compiled.
ohrstrom@1504 64 private boolean linkedOnly;
ohrstrom@1504 65
ohrstrom@1504 66 @Override
ohrstrom@1504 67 public boolean equals(Object o) {
ohrstrom@1504 68 return (o instanceof Source) && name.equals(((Source)o).name);
ohrstrom@1504 69 }
ohrstrom@1504 70
ohrstrom@1504 71 @Override
ohrstrom@1504 72 public int compareTo(Source o) {
ohrstrom@1504 73 return name.compareTo(o.name);
ohrstrom@1504 74 }
ohrstrom@1504 75
ohrstrom@1504 76 @Override
ohrstrom@1504 77 public int hashCode() {
ohrstrom@1504 78 return name.hashCode();
ohrstrom@1504 79 }
ohrstrom@1504 80
ohrstrom@1504 81 public Source(Module m, String n, File f, File r) {
ohrstrom@1504 82 name = n;
ohrstrom@1504 83 int dp = n.lastIndexOf(".");
ohrstrom@1504 84 if (dp != -1) {
ohrstrom@1504 85 suffix = n.substring(dp);
ohrstrom@1504 86 } else {
ohrstrom@1504 87 suffix = "";
ohrstrom@1504 88 }
ohrstrom@1504 89 file = f;
ohrstrom@1504 90 root = r;
ohrstrom@1504 91 lastModified = f.lastModified();
ohrstrom@1504 92 linkedOnly = false;
ohrstrom@1504 93 }
ohrstrom@1504 94
ohrstrom@1504 95 public Source(Package p, String n, long lm) {
ohrstrom@1504 96 pkg = p;
ohrstrom@1504 97 name = n;
ohrstrom@1504 98 int dp = n.lastIndexOf(".");
ohrstrom@1504 99 if (dp != -1) {
ohrstrom@1504 100 suffix = n.substring(dp);
ohrstrom@1504 101 } else {
ohrstrom@1504 102 suffix = "";
ohrstrom@1504 103 }
ohrstrom@1504 104 file = null;
ohrstrom@1504 105 root = null;
ohrstrom@1504 106 lastModified = lm;
ohrstrom@1504 107 linkedOnly = false;
ohrstrom@1504 108 int ls = n.lastIndexOf('/');
ohrstrom@1504 109 }
ohrstrom@1504 110
ohrstrom@1504 111 public String name() { return name; }
ohrstrom@1504 112 public String suffix() { return suffix; }
ohrstrom@1504 113 public Package pkg() { return pkg; }
ohrstrom@1504 114 public File file() { return file; }
ohrstrom@1504 115 public File root() { return root; }
ohrstrom@1504 116 public long lastModified() {
ohrstrom@1504 117 return lastModified;
ohrstrom@1504 118 }
ohrstrom@1504 119
ohrstrom@1504 120 public void setPackage(Package p) {
ohrstrom@1504 121 pkg = p;
ohrstrom@1504 122 }
ohrstrom@1504 123
ohrstrom@1504 124 public void markAsGenerated() {
ohrstrom@1504 125 isGenerated = true;
ohrstrom@1504 126 }
ohrstrom@1504 127
ohrstrom@1504 128 public boolean isGenerated() {
ohrstrom@1504 129 return isGenerated;
ohrstrom@1504 130 }
ohrstrom@1504 131
ohrstrom@1504 132 public void markAsLinkedOnly() {
ohrstrom@1504 133 linkedOnly = true;
ohrstrom@1504 134 }
ohrstrom@1504 135
ohrstrom@1504 136 public boolean isLinkedOnly() {
ohrstrom@1504 137 return linkedOnly;
ohrstrom@1504 138 }
ohrstrom@1504 139
ohrstrom@1504 140 private void save(StringBuilder b) {
ohrstrom@1504 141 String CL = linkedOnly?"L":"C";
ohrstrom@1504 142 String GS = isGenerated?"G":"S";
ohrstrom@1504 143 b.append(GS+" "+CL+" "+name+" "+file.lastModified()+"\n");
ohrstrom@1504 144 }
ohrstrom@1504 145 // Parse a line that looks like this:
ohrstrom@1504 146 // S C /code/alfa/A.java 1357631228000
ohrstrom@1504 147 static public Source load(Package lastPackage, String l, boolean isGenerated) {
ohrstrom@1504 148 int sp = l.indexOf(' ',4);
ohrstrom@1504 149 if (sp == -1) return null;
ohrstrom@1504 150 String name = l.substring(4,sp);
ohrstrom@1504 151 long last_modified = Long.parseLong(l.substring(sp+1));
ohrstrom@1504 152
ohrstrom@1504 153 boolean isLinkedOnly = false;
ohrstrom@1504 154 if (l.charAt(2) == 'L') {
ohrstrom@1504 155 isLinkedOnly = true;
ohrstrom@1504 156 } else if (l.charAt(2) == 'C') {
ohrstrom@1504 157 isLinkedOnly = false;
ohrstrom@1504 158 } else return null;
ohrstrom@1504 159
ohrstrom@1504 160 Source s = new Source(lastPackage, name, last_modified);
ohrstrom@1504 161 s.file = new File(name);
ohrstrom@1504 162 if (isGenerated) s.markAsGenerated();
ohrstrom@1504 163 if (isLinkedOnly) s.markAsLinkedOnly();
ohrstrom@1504 164 return s;
ohrstrom@1504 165 }
ohrstrom@1504 166
ohrstrom@1504 167 public static void saveSources(Map<String,Source> sources, StringBuilder b) {
ohrstrom@1504 168 List<String> sorted_sources = new ArrayList<String>();
ohrstrom@1504 169 for (String key : sources.keySet()) {
ohrstrom@1504 170 sorted_sources.add(key);
ohrstrom@1504 171 }
ohrstrom@1504 172 Collections.sort(sorted_sources);
ohrstrom@1504 173 for (String key : sorted_sources) {
ohrstrom@1504 174 Source s = sources.get(key);
ohrstrom@1504 175 s.save(b);
ohrstrom@1504 176 }
ohrstrom@1504 177 }
ohrstrom@1504 178
ohrstrom@1504 179 /**
ohrstrom@1504 180 * Recurse into the directory root and find all files matchine the excl/incl/exclfiles/inclfiles rules.
ohrstrom@1504 181 * Detects the existence of module-info.java files and presumes that the directory it resides in
ohrstrom@1504 182 * is the name of the current module.
ohrstrom@1504 183 */
ohrstrom@1504 184 static public void scanRoot(File root,
ohrstrom@1504 185 Set<String> suffixes,
ohrstrom@1504 186 List<String> excludes, List<String> includes,
ohrstrom@1504 187 List<String> excludeFiles, List<String> includeFiles,
ohrstrom@1504 188 Map<String,Source> foundFiles,
ohrstrom@1504 189 Map<String,Module> foundModules,
ohrstrom@1504 190 Module currentModule,
ohrstrom@1504 191 boolean permitSourcesWithoutPackage,
ohrstrom@1504 192 boolean inGensrc,
ohrstrom@1504 193 boolean inLinksrc)
ohrstrom@1504 194 throws ProblemException {
ohrstrom@1504 195
ohrstrom@1504 196 if (root == null) return;
ohrstrom@1504 197 int root_prefix = root.getPath().length()+1;
ohrstrom@1504 198 // This is the root source directory, it must not contain any Java sources files
ohrstrom@1504 199 // because we do not allow Java source files without a package.
ohrstrom@1504 200 // (Unless of course --permit-sources-without-package has been specified.)
ohrstrom@1504 201 // It might contain other source files however, (for -tr and -copy) these will
ohrstrom@1504 202 // always be included, since no package pattern can match the root directory.
ohrstrom@1504 203 currentModule = addFilesInDir(root, root_prefix, root, suffixes, permitSourcesWithoutPackage,
ohrstrom@1504 204 excludeFiles, includeFiles, false,
ohrstrom@1504 205 foundFiles, foundModules, currentModule,
ohrstrom@1504 206 inGensrc, inLinksrc);
ohrstrom@1504 207
ohrstrom@1504 208 File[] dirfiles = root.listFiles();
ohrstrom@1504 209 for (File d : dirfiles) {
ohrstrom@1504 210 if (d.isDirectory()) {
ohrstrom@1504 211 // Descend into the directory structure.
ohrstrom@1504 212 scanDirectory(d, root_prefix, root, suffixes,
ohrstrom@1504 213 excludes, includes, excludeFiles, includeFiles,
ohrstrom@1504 214 false, foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
ohrstrom@1504 215 }
ohrstrom@1504 216 }
ohrstrom@1504 217 }
ohrstrom@1504 218
ohrstrom@1504 219 /**
ohrstrom@1504 220 * Test if a path matches any of the patterns given.
ohrstrom@1504 221 * The pattern foo.bar matches only foo.bar
ohrstrom@1504 222 * The pattern foo.* matches foo.bar and foo.bar.zoo etc
ohrstrom@1504 223 */
ohrstrom@1504 224 static private boolean hasMatch(String path, List<String> patterns) {
ohrstrom@1504 225 for (String p : patterns) {
ohrstrom@1504 226 // Exact match
ohrstrom@1504 227 if (p.equals(path)) {
ohrstrom@1504 228 return true;
ohrstrom@1504 229 }
ohrstrom@1504 230 // Single dot the end matches this package and all its subpackages.
ohrstrom@1504 231 if (p.endsWith(".*")) {
ohrstrom@1504 232 // Remove the wildcard
ohrstrom@1504 233 String patprefix = p.substring(0,p.length()-2);
ohrstrom@1504 234 // Does the path start with the pattern prefix?
ohrstrom@1504 235 if (path.startsWith(patprefix)) {
ohrstrom@1504 236 // If the path has the same length as the pattern prefix, then it is a match.
ohrstrom@1504 237 // If the path is longer, then make sure that
ohrstrom@1504 238 // the next part of the path starts with a dot (.) to prevent
ohrstrom@1504 239 // wildcard matching in the middle of a package name.
ohrstrom@1504 240 if (path.length()==patprefix.length() || path.charAt(patprefix.length())=='.') {
ohrstrom@1504 241 return true;
ohrstrom@1504 242 }
ohrstrom@1504 243 }
ohrstrom@1504 244 }
ohrstrom@1504 245 }
ohrstrom@1504 246 return false;
ohrstrom@1504 247 }
ohrstrom@1504 248
ohrstrom@1504 249 /**
ohrstrom@1504 250 * Matches patterns with the asterisk first. */
ohrstrom@1504 251 // The pattern foo/bar.java only matches foo/bar.java
ohrstrom@1504 252 // The pattern */bar.java matches foo/bar.java and zoo/bar.java etc
ohrstrom@1504 253 static private boolean hasFileMatch(String path, List<String> patterns) {
ohrstrom@1504 254 path = Util.normalizeDriveLetter(path);
ohrstrom@1504 255 for (String p : patterns) {
ohrstrom@1504 256 // Exact match
ohrstrom@1504 257 if (p.equals(path)) {
ohrstrom@1504 258 return true;
ohrstrom@1504 259 }
ohrstrom@1504 260 // Single dot the end matches this package and all its subpackages.
ohrstrom@1504 261 if (p.startsWith("*")) {
ohrstrom@1504 262 // Remove the wildcard
ohrstrom@1504 263 String patsuffix = p.substring(1);
ohrstrom@1504 264 // Does the path start with the pattern prefix?
ohrstrom@1504 265 if (path.endsWith(patsuffix)) {
ohrstrom@1504 266 return true;
ohrstrom@1504 267 }
ohrstrom@1504 268 }
ohrstrom@1504 269 }
ohrstrom@1504 270 return false;
ohrstrom@1504 271 }
ohrstrom@1504 272
ohrstrom@1504 273 /**
ohrstrom@1504 274 * Add the files in the directory, assuming that the file has not been excluded.
ohrstrom@1504 275 * Returns a fresh Module object, if this was a dir with a module-info.java file.
ohrstrom@1504 276 */
ohrstrom@1504 277 static private Module addFilesInDir(File dir, int rootPrefix, File root,
ohrstrom@1504 278 Set<String> suffixes, boolean allow_javas,
ohrstrom@1504 279 List<String> excludeFiles, List<String> includeFiles, boolean all,
ohrstrom@1504 280 Map<String,Source> foundFiles,
ohrstrom@1504 281 Map<String,Module> foundModules,
ohrstrom@1504 282 Module currentModule,
ohrstrom@1504 283 boolean inGensrc,
ohrstrom@1504 284 boolean inLinksrc)
ohrstrom@1504 285 throws ProblemException
ohrstrom@1504 286 {
ohrstrom@1504 287 for (File f : dir.listFiles()) {
ohrstrom@1504 288 if (f.isFile()) {
ohrstrom@1504 289 boolean should_add =
ohrstrom@1504 290 (excludeFiles == null || excludeFiles.isEmpty() || !hasFileMatch(f.getPath(), excludeFiles))
ohrstrom@1504 291 && (includeFiles == null || includeFiles.isEmpty() || hasFileMatch(f.getPath(), includeFiles));
ohrstrom@1504 292
ohrstrom@1504 293 if (should_add) {
ohrstrom@1504 294 if (!allow_javas && f.getName().endsWith(".java")) {
ohrstrom@1504 295 throw new ProblemException("No .java files are allowed in the source root "+dir.getPath()+
ohrstrom@1504 296 ", please remove "+f.getName());
ohrstrom@1504 297 }
ohrstrom@1504 298 // Extract the file name relative the root.
ohrstrom@1504 299 String fn = f.getPath().substring(rootPrefix);
ohrstrom@1504 300 // Extract the package name.
ohrstrom@1504 301 int sp = fn.lastIndexOf(File.separatorChar);
ohrstrom@1504 302 String pkg = "";
ohrstrom@1504 303 if (sp != -1) {
ohrstrom@1504 304 pkg = fn.substring(0,sp).replace(File.separatorChar,'.');
ohrstrom@1504 305 }
ohrstrom@1504 306 // Is this a module-info.java file?
ohrstrom@1504 307 if (fn.endsWith("module-info.java")) {
ohrstrom@1504 308 // Aha! We have recursed into a module!
ohrstrom@1504 309 if (!currentModule.name().equals("")) {
ohrstrom@1504 310 throw new ProblemException("You have an extra module-info.java inside a module! Please remove "+fn);
ohrstrom@1504 311 }
ohrstrom@1504 312 String module_name = fn.substring(0,fn.length()-16);
ohrstrom@1504 313 currentModule = new Module(module_name, f.getPath());
ohrstrom@1504 314 foundModules.put(module_name, currentModule);
ohrstrom@1504 315 }
ohrstrom@1504 316 // Extract the suffix.
ohrstrom@1504 317 int dp = fn.lastIndexOf(".");
ohrstrom@1504 318 String suffix = "";
ohrstrom@1504 319 if (dp > 0) {
ohrstrom@1504 320 suffix = fn.substring(dp);
ohrstrom@1504 321 }
ohrstrom@1504 322 // Should the file be added?
ohrstrom@1504 323 if (all || suffixes.contains(suffix)) {
ohrstrom@1504 324 Source of = foundFiles.get(f.getPath());
ohrstrom@1504 325 if (of != null) {
ohrstrom@1504 326 throw new ProblemException("You have already added the file "+fn+" from "+of.file().getPath());
ohrstrom@1504 327 }
ohrstrom@1504 328 of = currentModule.lookupSource(f.getPath());
ohrstrom@1504 329 if (of != null) {
ohrstrom@1504 330 // Oups, the source is already added, could be ok, could be not, lets check.
ohrstrom@1504 331 if (inLinksrc) {
ohrstrom@1504 332 // So we are collecting sources for linking only.
ohrstrom@1504 333 if (of.isLinkedOnly()) {
ohrstrom@1504 334 // Ouch, this one is also for linking only. Bad.
ohrstrom@1504 335 throw new ProblemException("You have already added the link only file "+fn+" from "+of.file().getPath());
ohrstrom@1504 336 }
ohrstrom@1504 337 // Ok, the existing source is to be compiled. Thus this link only is redundant
ohrstrom@1504 338 // since all compiled are also linked to. Continue to the next source.
ohrstrom@1504 339 // But we need to add the source, so that it will be visible to linking,
ohrstrom@1504 340 // if not the multi core compile will fail because a JavaCompiler cannot
ohrstrom@1504 341 // find the necessary dependencies for its part of the source.
ohrstrom@1504 342 foundFiles.put(f.getPath(), of);
ohrstrom@1504 343 continue;
ohrstrom@1504 344 } else {
ohrstrom@1504 345 // We are looking for sources to compile, if we find an existing to be compiled
ohrstrom@1504 346 // source with the same name, it is an internal error, since we must
ohrstrom@1504 347 // find the sources to be compiled before we find the sources to be linked to.
ohrstrom@1504 348 throw new ProblemException("Internal error: Double add of file "+fn+" from "+of.file().getPath());
ohrstrom@1504 349 }
ohrstrom@1504 350 }
ohrstrom@1504 351 Source s = new Source(currentModule, f.getPath(), f, root);
ohrstrom@1504 352 if (inGensrc) s.markAsGenerated();
ohrstrom@1504 353 if (inLinksrc) {
ohrstrom@1504 354 s.markAsLinkedOnly();
ohrstrom@1504 355 }
ohrstrom@1504 356 pkg = currentModule.name()+":"+pkg;
ohrstrom@1504 357 foundFiles.put(f.getPath(), s);
ohrstrom@1504 358 currentModule.addSource(pkg, s);
ohrstrom@1504 359 }
ohrstrom@1504 360 }
ohrstrom@1504 361 }
ohrstrom@1504 362 }
ohrstrom@1504 363 return currentModule;
ohrstrom@1504 364 }
ohrstrom@1504 365
ohrstrom@1504 366 private static boolean gurka = false;
ohrstrom@1504 367
ohrstrom@1504 368 static private void scanDirectory(File dir, int rootPrefix, File root,
ohrstrom@1504 369 Set<String> suffixes,
ohrstrom@1504 370 List<String> excludes, List<String> includes,
ohrstrom@1504 371 List<String> excludeFiles, List<String> includeFiles, boolean all,
ohrstrom@1504 372 Map<String,Source> foundFiles,
ohrstrom@1504 373 Map<String,Module> foundModules,
ohrstrom@1504 374 Module currentModule, boolean inGensrc, boolean inLinksrc)
ohrstrom@1504 375 throws ProblemException {
ohrstrom@1504 376
ohrstrom@1504 377 String pkg_name = "";
ohrstrom@1504 378 // Remove the root prefix from the dir path, and replace file separator with dots
ohrstrom@1504 379 // to get the package name.
ohrstrom@1504 380 if (dir.getPath().length() > rootPrefix) {
ohrstrom@1504 381 pkg_name = dir.getPath().substring(rootPrefix).replace(File.separatorChar,'.');
ohrstrom@1504 382 }
ohrstrom@1504 383 // Should this package directory be included and not excluded?
ohrstrom@1504 384 if (all || ((includes==null || includes.isEmpty() || hasMatch(pkg_name, includes)) &&
ohrstrom@1504 385 (excludes==null || excludes.isEmpty() || !hasMatch(pkg_name, excludes)))) {
ohrstrom@1504 386 // Add the source files.
ohrstrom@1504 387 currentModule = addFilesInDir(dir, rootPrefix, root, suffixes, true, excludeFiles, includeFiles, all,
ohrstrom@1504 388 foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
ohrstrom@1504 389 }
ohrstrom@1504 390
ohrstrom@1504 391 for (File d : dir.listFiles()) {
ohrstrom@1504 392 if (d.isDirectory()) {
ohrstrom@1504 393 // Descend into the directory structure.
ohrstrom@1504 394 scanDirectory(d, rootPrefix, root, suffixes,
ohrstrom@1504 395 excludes, includes, excludeFiles, includeFiles, all,
ohrstrom@1504 396 foundFiles, foundModules, currentModule, inGensrc, inLinksrc);
ohrstrom@1504 397 }
ohrstrom@1504 398 }
ohrstrom@1504 399 }
ohrstrom@1504 400 }

mercurial