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

Thu, 31 Aug 2017 15:17:03 +0800

author
aoqi
date
Thu, 31 Aug 2017 15:17:03 +0800
changeset 2525
2eb010b6cb22
parent 2227
998b10c43157
parent 0
959103a6100f
permissions
-rw-r--r--

merge

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

mercurial