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

Wed, 27 Apr 2016 01:34:52 +0800

author
aoqi
date
Wed, 27 Apr 2016 01:34:52 +0800
changeset 0
959103a6100f
child 2525
2eb010b6cb22
permissions
-rw-r--r--

Initial load
http://hg.openjdk.java.net/jdk8u/jdk8u/langtools/
changeset: 2573:53ca196be1ae
tag: jdk8u25-b17

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.io.IOException;
aoqi@0 30 import java.io.PrintStream;
aoqi@0 31 import java.util.*;
aoqi@0 32 import java.util.regex.Matcher;
aoqi@0 33 import java.util.regex.Pattern;
aoqi@0 34
aoqi@0 35 import com.sun.tools.sjavac.server.JavacServer;
aoqi@0 36
aoqi@0 37 /**
aoqi@0 38 * The main class of the smart javac wrapper tool.
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 Main {
aoqi@0 46
aoqi@0 47 /* This is a smart javac wrapper primarily used when building the OpenJDK,
aoqi@0 48 though other projects are welcome to use it too. But please be aware
aoqi@0 49 that it is not an official api and will change in the future.
aoqi@0 50 (We really mean it!)
aoqi@0 51
aoqi@0 52 Goals:
aoqi@0 53
aoqi@0 54 ** Create a state file, containing information about the build, so
aoqi@0 55 that incremental builds only rebuild what is necessary. Also the
aoqi@0 56 state file can be used by make/ant to detect when to trigger
aoqi@0 57 a call to the smart javac wrapper.
aoqi@0 58
aoqi@0 59 This file is called bin/javac_state (assuming that you specified "-d bin")
aoqi@0 60 Thus the simplest makefile is:
aoqi@0 61
aoqi@0 62 SJAVAC=java -cp .../tools.jar com.sun.tools.sjavac.Main
aoqi@0 63 SRCS=$(shell find src -name "*.java")
aoqi@0 64 bin/javac_state : $(SRCS)
aoqi@0 65 $(SJAVAC) src -d bin
aoqi@0 66
aoqi@0 67 This makefile will run very fast and detect properly when Java code needs to
aoqi@0 68 be recompiled. The smart javac wrapper will then use the information in java_state
aoqi@0 69 to do an efficient incremental compile.
aoqi@0 70
aoqi@0 71 Previously it was near enough impossible to write an efficient makefile for Java
aoqi@0 72 with support for incremental builds and dependency tracking.
aoqi@0 73
aoqi@0 74 ** Separate java sources to be compiled from java
aoqi@0 75 sources used >only< for linking. The options:
aoqi@0 76
aoqi@0 77 "dir" points to root dir with sources to be compiled
aoqi@0 78 "-sourcepath dir" points to root dir with sources used only for linking
aoqi@0 79 "-classpath dir" points to dir with classes used only for linking (as before)
aoqi@0 80
aoqi@0 81 ** Use all cores for compilation by default.
aoqi@0 82 "-j 4" limit the number of cores to 4.
aoqi@0 83 For the moment, the sjavac server additionally limits the number of cores to three.
aoqi@0 84 This will improve in the future when more sharing is performed between concurrent JavaCompilers.
aoqi@0 85
aoqi@0 86 ** Basic translation support from other sources to java, and then compilation of the generated java.
aoqi@0 87 This functionality might be moved into annotation processors instead.
aoqi@0 88 Again this is driven by the OpenJDK sources where properties and a few other types of files
aoqi@0 89 are converted into Java sources regularily. The javac_state embraces copy and tr, and perform
aoqi@0 90 incremental recompiles and copying for these as well. META-INF will be a special copy rule
aoqi@0 91 that will copy any files found below any META-INF dir in src to the bin/META-INF dir.
aoqi@0 92 "-copy .gif"
aoqi@0 93 "-copy META-INF"
aoqi@0 94 "-tr .prop=com.sun.tools.javac.smart.CompileProperties
aoqi@0 95 "-tr .propp=com.sun.tools.javac.smart.CompileProperties,java.util.ListResourceBundle
aoqi@0 96 "-tr .proppp=com.sun.tools.javac.smart.CompileProperties,sun.util.resources.LocaleNamesBundle
aoqi@0 97
aoqi@0 98 ** Control which classes in the src,sourcepath and classpath that javac is allowed to see.
aoqi@0 99 Again, this is necessary to deal with the source code structure of the OpenJDK which is
aoqi@0 100 intricate (read messy).
aoqi@0 101
aoqi@0 102 "-i tools.*" to include the tools package and all its subpackages in the build.
aoqi@0 103 "-x tools.net.aviancarrier.*" to exclude the aviancarrier package and all its sources and subpackages.
aoqi@0 104 "-x tools.net.drums" to exclude the drums package only, keep its subpackages.
aoqi@0 105 "-xf tools/net/Bar.java" // Do not compile this file...
aoqi@0 106 "-xf *Bor.java" // Do not compile Bor.java wherever it is found, BUT do compile ABor.java!
aoqi@0 107 "-if tools/net/Bor.java" // Only compile this file...odd, but sometimes used.
aoqi@0 108
aoqi@0 109 ** The smart javac wrapper is driven by the modification time on the source files and compared
aoqi@0 110 to the modification times written into the javac_state file.
aoqi@0 111
aoqi@0 112 It does not compare the modification time of the source with the modification time of the artifact.
aoqi@0 113 However it will detect if the modification time of an artifact has changed compared to the java_state,
aoqi@0 114 and this will trigger a delete of the artifact and a subsequent recompile of the source.
aoqi@0 115
aoqi@0 116 The smart javac wrapper is not a generic makefile/ant system. Its purpose is to compile java source
aoqi@0 117 as the final step before the output dir is finalized and immediately jared, or jmodded. The output
aoqi@0 118 dir should be considered opaque. Do not write into the outputdir yourself!
aoqi@0 119 Any artifacts found in the outputdir that javac_state does not know of, will be deleted!
aoqi@0 120 This can however be prevented, using the switch --permit-unidentified-artifacts
aoqi@0 121 This switch is necessary when build the OpenJDK because its makefiles still write directly to
aoqi@0 122 the output classes dirs.
aoqi@0 123
aoqi@0 124 Any makefile/ant rules that want to put contents into the outputdir should put the content
aoqi@0 125 in one of several source roots. Static content that is under version control, can be put in the same source
aoqi@0 126 code tree as the Java sources. Dynamic content that is generated by make/ant on the fly, should
aoqi@0 127 be put in a separate gensrc_stuff root. The smart javac wrapper call will then take the arguments:
aoqi@0 128 "gensrc_stuff src -d bin"
aoqi@0 129
aoqi@0 130 The command line:
aoqi@0 131 java -cp tools.jar com.sun.tools.sjavac.Main \
aoqi@0 132 -i "com.bar.*" -x "com.bar.foo.*" \
aoqi@0 133 first_root \
aoqi@0 134 -i "com.bar.foo.*" \
aoqi@0 135 second_root \
aoqi@0 136 -x "org.net.*" \
aoqi@0 137 -sourcepath link_root_sources \
aoqi@0 138 -classpath link_root_classes \
aoqi@0 139 -d bin
aoqi@0 140
aoqi@0 141 Will compile all sources for package com.bar and its subpackages, found below first_root,
aoqi@0 142 except the package com.bar.foo (and its subpackages), for which the sources are picked
aoqi@0 143 from second_root instead. It will link against classes in link_root_classes and against
aoqi@0 144 sources in link_root_sources, but will not see (try to link against) sources matching org.net.*
aoqi@0 145 but will link against org.net* classes (if they exist) in link_root_classes.
aoqi@0 146
aoqi@0 147 (If you want a set of complex filter rules to be applied to several source directories, without
aoqi@0 148 having to repeat the the filter rules for each root. You can use the explicit -src option. For example:
aoqi@0 149 sjavac -x "com.foo.*" -src root1:root2:root3 )
aoqi@0 150
aoqi@0 151 The resulting classes are written into bin.
aoqi@0 152 */
aoqi@0 153
aoqi@0 154 // This is the final destination for classes and copied files.
aoqi@0 155 private File bin_dir;
aoqi@0 156 // This is where the annotation process will put generated sources.
aoqi@0 157 private File gensrc_dir;
aoqi@0 158 // This is where javac -h puts the generated c-header files.
aoqi@0 159 private File header_dir;
aoqi@0 160
aoqi@0 161 // This file contains the list of sources genereated by the makefile.
aoqi@0 162 // We double check that our calculated list of sources matches this list,
aoqi@0 163 // if not, then we terminate with an error!
aoqi@0 164 private File makefile_source_list;
aoqi@0 165 // The challenging task to manage an incremental build is done by javac_state.
aoqi@0 166 private JavacState javac_state;
aoqi@0 167
aoqi@0 168 // The suffix rules tells you for example, that .java files should be compiled,
aoqi@0 169 // and .html files should be copied and .properties files be translated.
aoqi@0 170 Map<String,Transformer> suffix_rules;
aoqi@0 171
aoqi@0 172 public static void main(String... args) {
aoqi@0 173 if (args.length > 0 && args[0].startsWith("--startserver:")) {
aoqi@0 174 if (args.length>1) {
aoqi@0 175 Log.error("When spawning a background server, only a single --startserver argument is allowed.");
aoqi@0 176 return;
aoqi@0 177 }
aoqi@0 178 // Spawn a background server.
aoqi@0 179 int rc = JavacServer.startServer(args[0], System.err);
aoqi@0 180 System.exit(rc);
aoqi@0 181 }
aoqi@0 182 Main main = new Main();
aoqi@0 183 int rc = main.go(args, System.out, System.err);
aoqi@0 184 // Remove the portfile, but only if this background=false was used.
aoqi@0 185 JavacServer.cleanup(args);
aoqi@0 186 System.exit(rc);
aoqi@0 187 }
aoqi@0 188
aoqi@0 189 private void printHelp() {
aoqi@0 190 System.out.println("Usage: sjavac <options>\n"+
aoqi@0 191 "where required options are:\n"+
aoqi@0 192 "dir Compile all sources in dir recursively\n"+
aoqi@0 193 "-d dir Store generated classes here and the javac_state file\n"+
aoqi@0 194 "--server:portfile=/tmp/abc Use a background sjavac server\n\n"+
aoqi@0 195 "All other arguments as javac, except -implicit:none which is forced by default.\n"+
aoqi@0 196 "No java source files can be supplied on the command line, nor can an @file be supplied.\n\n"+
aoqi@0 197 "Warning!\n"+
aoqi@0 198 "This tool might disappear at any time, and its command line options might change at any time!");
aoqi@0 199 }
aoqi@0 200
aoqi@0 201 public int go(String[] args, PrintStream out, PrintStream err) {
aoqi@0 202 try {
aoqi@0 203 if (args.length == 0 || findJavaSourceFiles(args) || findAtFile(args) || null==Util.findServerSettings(args)) {
aoqi@0 204 printHelp();
aoqi@0 205 return 0;
aoqi@0 206 }
aoqi@0 207
aoqi@0 208 Log.setLogLevel(findLogLevel(args), out, err);
aoqi@0 209 String server_settings = Util.findServerSettings(args);
aoqi@0 210 args = verifyImplicitOption(args);
aoqi@0 211 // Find the source root directories, and add the -src option before these, if not there already.
aoqi@0 212 args = addSrcBeforeDirectories(args);
aoqi@0 213 // Check that there is at least one -src supplied.
aoqi@0 214 checkSrcOption(args);
aoqi@0 215 // Check that there is one -d supplied.
aoqi@0 216 bin_dir = findDirectoryOption(args,"-d","output", true, false, true);
aoqi@0 217 gensrc_dir = findDirectoryOption(args,"-s","gensrc", false, false, true);
aoqi@0 218 header_dir = findDirectoryOption(args,"-h","headers", false, false, true);
aoqi@0 219 makefile_source_list = findFileOption(args,"--compare-found-sources","makefile source list", false);
aoqi@0 220
aoqi@0 221 // Load the prev build state database.
aoqi@0 222 javac_state = JavacState.load(args, bin_dir, gensrc_dir, header_dir,
aoqi@0 223 findBooleanOption(args, "--permit-unidentified-artifacts"), out, err);
aoqi@0 224
aoqi@0 225 // Setup the suffix rules from the command line.
aoqi@0 226 suffix_rules = javac_state.getJavaSuffixRule();
aoqi@0 227 findTranslateOptions(args, suffix_rules);
aoqi@0 228 if (suffix_rules.keySet().size() > 1 && gensrc_dir == null) {
aoqi@0 229 Log.error("You have translators but no gensrc dir (-s) specified!");
aoqi@0 230 return -1;
aoqi@0 231 }
aoqi@0 232 findCopyOptions(args, suffix_rules);
aoqi@0 233
aoqi@0 234 // All found modules are put here.
aoqi@0 235 Map<String,Module> modules = new HashMap<String,Module>();
aoqi@0 236 // We start out in the legacy empty no-name module.
aoqi@0 237 // As soon as we stumble on a module-info.java file we change to that module.
aoqi@0 238 Module current_module = new Module("", "");
aoqi@0 239 modules.put("", current_module);
aoqi@0 240
aoqi@0 241 // Find all sources, use the suffix rules to know which files are sources.
aoqi@0 242 Map<String,Source> sources = new HashMap<String,Source>();
aoqi@0 243 // Find the files, this will automatically populate the found modules
aoqi@0 244 // with found packages where the sources are found!
aoqi@0 245 findFiles(args, "-src", suffix_rules.keySet(), sources, modules, current_module, false);
aoqi@0 246
aoqi@0 247 if (sources.isEmpty()) {
aoqi@0 248 Log.error("Found nothing to compile!");
aoqi@0 249 return -1;
aoqi@0 250 }
aoqi@0 251
aoqi@0 252 // Create a map of all source files that are available for linking. Both -src and
aoqi@0 253 // -sourcepath point to such files. It is possible to specify multiple
aoqi@0 254 // -sourcepath options to enable different filtering rules. If the
aoqi@0 255 // filters are the same for multiple sourcepaths, they may be concatenated
aoqi@0 256 // using :(;). Before sending the list of sourcepaths to javac, they are
aoqi@0 257 // all concatenated. The list created here is used by the SmartFileWrapper to
aoqi@0 258 // make sure only the correct sources are actually available.
aoqi@0 259 // We might find more modules here as well.
aoqi@0 260 Map<String,Source> sources_to_link_to = new HashMap<String,Source>();
aoqi@0 261 findFiles(args, "-src", Util.set(".java"), sources_to_link_to, modules, current_module, true);
aoqi@0 262 findFiles(args, "-sourcepath", Util.set(".java"), sources_to_link_to, modules, current_module, true);
aoqi@0 263 // Rewrite the -src option to make it through to the javac instances.
aoqi@0 264 rewriteOptions(args, "-src", "-sourcepath");
aoqi@0 265
aoqi@0 266 // Find all class files allowable for linking.
aoqi@0 267 // And pickup knowledge of all modules found here.
aoqi@0 268 // This cannot currently filter classes inside jar files.
aoqi@0 269 // Map<String,Source> classes_to_link_to = new HashMap<String,Source>();
aoqi@0 270 // findFiles(args, "-classpath", Util.set(".class"), classes_to_link_to, modules, current_module, true);
aoqi@0 271
aoqi@0 272 // Find all module sources allowable for linking.
aoqi@0 273 // Map<String,Source> modules_to_link_to = new HashMap<String,Source>();
aoqi@0 274 // findFiles(args, "-modulepath", Util.set(".class"), modules_to_link_to, modules, current_module, true);
aoqi@0 275
aoqi@0 276 // Add the set of sources to the build database.
aoqi@0 277 javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
aoqi@0 278 javac_state.now().checkInternalState("checking sources", false, sources);
aoqi@0 279 javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to);
aoqi@0 280 javac_state.setVisibleSources(sources_to_link_to);
aoqi@0 281
aoqi@0 282 // If there is any change in the source files, taint packages
aoqi@0 283 // and mark the database in need of saving.
aoqi@0 284 javac_state.checkSourceStatus(false);
aoqi@0 285
aoqi@0 286 // Find all existing artifacts. Their timestamp will match the last modified timestamps stored
aoqi@0 287 // in javac_state, simply because loading of the JavacState will clean out all artifacts
aoqi@0 288 // that do not match the javac_state database.
aoqi@0 289 javac_state.findAllArtifacts();
aoqi@0 290
aoqi@0 291 // Remove unidentified artifacts from the bin, gensrc and header dirs.
aoqi@0 292 // (Unless we allow them to be there.)
aoqi@0 293 // I.e. artifacts that are not known according to the build database (javac_state).
aoqi@0 294 // For examples, files that have been manually copied into these dirs.
aoqi@0 295 // Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp
aoqi@0 296 // in javac_state) have already been removed when the javac_state was loaded.
aoqi@0 297 if (!findBooleanOption(args, "--permit-unidentified-artifacts")) {
aoqi@0 298 javac_state.removeUnidentifiedArtifacts();
aoqi@0 299 }
aoqi@0 300 // Go through all sources and taint all packages that miss artifacts.
aoqi@0 301 javac_state.taintPackagesThatMissArtifacts();
aoqi@0 302
aoqi@0 303 // Now clean out all known artifacts belonging to tainted packages.
aoqi@0 304 javac_state.deleteClassArtifactsInTaintedPackages();
aoqi@0 305 // Copy files, for example property files, images files, xml files etc etc.
aoqi@0 306 javac_state.performCopying(bin_dir, suffix_rules);
aoqi@0 307 // Translate files, for example compile properties or compile idls.
aoqi@0 308 javac_state.performTranslation(gensrc_dir, suffix_rules);
aoqi@0 309 // Add any potentially generated java sources to the tobe compiled list.
aoqi@0 310 // (Generated sources must always have a package.)
aoqi@0 311 Map<String,Source> generated_sources = new HashMap<String,Source>();
aoqi@0 312 Source.scanRoot(gensrc_dir, Util.set(".java"), null, null, null, null,
aoqi@0 313 generated_sources, modules, current_module, false, true, false);
aoqi@0 314 javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
aoqi@0 315 // Recheck the the source files and their timestamps again.
aoqi@0 316 javac_state.checkSourceStatus(true);
aoqi@0 317
aoqi@0 318 // Now do a safety check that the list of source files is identical
aoqi@0 319 // to the list Make believes we are compiling. If we do not get this
aoqi@0 320 // right, then incremental builds will fail with subtility.
aoqi@0 321 // If any difference is detected, then we will fail hard here.
aoqi@0 322 // This is an important safety net.
aoqi@0 323 javac_state.compareWithMakefileList(makefile_source_list);
aoqi@0 324
aoqi@0 325 // Do the compilations, repeatedly until no tainted packages exist.
aoqi@0 326 boolean again;
aoqi@0 327 // Collect the name of all compiled packages.
aoqi@0 328 Set<String> recently_compiled = new HashSet<String>();
aoqi@0 329 boolean[] rc = new boolean[1];
aoqi@0 330 do {
aoqi@0 331 // Clean out artifacts in tainted packages.
aoqi@0 332 javac_state.deleteClassArtifactsInTaintedPackages();
aoqi@0 333 again = javac_state.performJavaCompilations(bin_dir, server_settings, args, recently_compiled, rc);
aoqi@0 334 if (!rc[0]) break;
aoqi@0 335 } while (again);
aoqi@0 336 // Only update the state if the compile went well.
aoqi@0 337 if (rc[0]) {
aoqi@0 338 javac_state.save();
aoqi@0 339 // Reflatten only the artifacts.
aoqi@0 340 javac_state.now().flattenArtifacts(modules);
aoqi@0 341 // Remove artifacts that were generated during the last compile, but not this one.
aoqi@0 342 javac_state.removeSuperfluousArtifacts(recently_compiled);
aoqi@0 343 }
aoqi@0 344 return rc[0] ? 0 : -1;
aoqi@0 345 } catch (ProblemException e) {
aoqi@0 346 Log.error(e.getMessage());
aoqi@0 347 return -1;
aoqi@0 348 } catch (Exception e) {
aoqi@0 349 e.printStackTrace(err);
aoqi@0 350 return -1;
aoqi@0 351 }
aoqi@0 352 }
aoqi@0 353
aoqi@0 354 /**
aoqi@0 355 * Are java source files passed on the command line?
aoqi@0 356 */
aoqi@0 357 private boolean findJavaSourceFiles(String[] args) {
aoqi@0 358 String prev = "";
aoqi@0 359 for (String s : args) {
aoqi@0 360 if (s.endsWith(".java") && !prev.equals("-xf") && !prev.equals("-if")) {
aoqi@0 361 return true;
aoqi@0 362 }
aoqi@0 363 prev = s;
aoqi@0 364 }
aoqi@0 365 return false;
aoqi@0 366 }
aoqi@0 367
aoqi@0 368 /**
aoqi@0 369 * Is an at file passed on the command line?
aoqi@0 370 */
aoqi@0 371 private boolean findAtFile(String[] args) {
aoqi@0 372 for (String s : args) {
aoqi@0 373 if (s.startsWith("@")) {
aoqi@0 374 return true;
aoqi@0 375 }
aoqi@0 376 }
aoqi@0 377 return false;
aoqi@0 378 }
aoqi@0 379
aoqi@0 380 /**
aoqi@0 381 * Find the log level setting.
aoqi@0 382 */
aoqi@0 383 private String findLogLevel(String[] args) {
aoqi@0 384 for (String s : args) {
aoqi@0 385 if (s.startsWith("--log=") && s.length()>6) {
aoqi@0 386 return s.substring(6);
aoqi@0 387 }
aoqi@0 388 if (s.equals("-verbose")) {
aoqi@0 389 return "info";
aoqi@0 390 }
aoqi@0 391 }
aoqi@0 392 return "info";
aoqi@0 393 }
aoqi@0 394
aoqi@0 395 /**
aoqi@0 396 * Remove smart javac wrapper arguments, before feeding
aoqi@0 397 * the args to the plain javac.
aoqi@0 398 */
aoqi@0 399 static String[] removeWrapperArgs(String[] args) {
aoqi@0 400 String[] out = new String[args.length];
aoqi@0 401 // The first source path index is remembered
aoqi@0 402 // here. So that all following can be concatenated to it.
aoqi@0 403 int source_path = -1;
aoqi@0 404 // The same for class path.
aoqi@0 405 int class_path = -1;
aoqi@0 406 // And module path.
aoqi@0 407 int module_path = -1;
aoqi@0 408 int j = 0;
aoqi@0 409 for (int i = 0; i<args.length; ++i) {
aoqi@0 410 if (args[i].equals("-src") ||
aoqi@0 411 args[i].equals("-x") ||
aoqi@0 412 args[i].equals("-i") ||
aoqi@0 413 args[i].equals("-xf") ||
aoqi@0 414 args[i].equals("-if") ||
aoqi@0 415 args[i].equals("-copy") ||
aoqi@0 416 args[i].equals("-tr") ||
aoqi@0 417 args[i].equals("-j")) {
aoqi@0 418 // Just skip it and skip following value
aoqi@0 419 i++;
aoqi@0 420 } else if (args[i].startsWith("--server:")) {
aoqi@0 421 // Just skip it.
aoqi@0 422 } else if (args[i].startsWith("--log=")) {
aoqi@0 423 // Just skip it.
aoqi@0 424 } else if (args[i].equals("--permit-unidentified-artifacts")) {
aoqi@0 425 // Just skip it.
aoqi@0 426 } else if (args[i].equals("--permit-sources-without-package")) {
aoqi@0 427 // Just skip it.
aoqi@0 428 } else if (args[i].equals("--compare-found-sources")) {
aoqi@0 429 // Just skip it and skip verify file name
aoqi@0 430 i++;
aoqi@0 431 } else if (args[i].equals("-sourcepath")) {
aoqi@0 432 if (source_path == -1) {
aoqi@0 433 source_path = j;
aoqi@0 434 out[j] = args[i];
aoqi@0 435 out[j+1] = args[i+1];
aoqi@0 436 j+=2;
aoqi@0 437 i++;
aoqi@0 438 } else {
aoqi@0 439 // Skip this and its argument, but
aoqi@0 440 // append argument to found sourcepath.
aoqi@0 441 out[source_path+1] = out[source_path+1]+File.pathSeparatorChar+args[i+1];
aoqi@0 442 i++;
aoqi@0 443 }
aoqi@0 444 } else if (args[i].equals("-classpath") || args[i].equals("-cp")) {
aoqi@0 445 if (class_path == -1) {
aoqi@0 446 class_path = j;
aoqi@0 447 out[j] = args[i];
aoqi@0 448 out[j+1] = args[i+1];
aoqi@0 449 j+=2;
aoqi@0 450 i++;
aoqi@0 451 } else {
aoqi@0 452 // Skip this and its argument, but
aoqi@0 453 // append argument to found sourcepath.
aoqi@0 454 out[class_path+1] = out[class_path+1]+File.pathSeparatorChar+args[i+1];
aoqi@0 455 i++;
aoqi@0 456 }
aoqi@0 457 } else if (args[i].equals("-modulepath")) {
aoqi@0 458 if (module_path == -1) {
aoqi@0 459 module_path = j;
aoqi@0 460 out[j] = args[i];
aoqi@0 461 out[j+1] = args[i+1];
aoqi@0 462 j+=2;
aoqi@0 463 i++;
aoqi@0 464 } else {
aoqi@0 465 // Skip this and its argument, but
aoqi@0 466 // append argument to found sourcepath.
aoqi@0 467 out[module_path+1] = out[module_path+1]+File.pathSeparatorChar+args[i+1];
aoqi@0 468 i++;
aoqi@0 469 }
aoqi@0 470 } else {
aoqi@0 471 // Copy argument.
aoqi@0 472 out[j] = args[i];
aoqi@0 473 j++;
aoqi@0 474 }
aoqi@0 475 }
aoqi@0 476 String[] ret = new String[j];
aoqi@0 477 System.arraycopy(out, 0, ret, 0, j);
aoqi@0 478 return ret;
aoqi@0 479 }
aoqi@0 480
aoqi@0 481 /**
aoqi@0 482 * Make sure directory exist, create it if not.
aoqi@0 483 */
aoqi@0 484 private static boolean makeSureExists(File dir) {
aoqi@0 485 // Make sure the dest directories exist.
aoqi@0 486 if (!dir.exists()) {
aoqi@0 487 if (!dir.mkdirs()) {
aoqi@0 488 Log.error("Could not create the directory "+dir.getPath());
aoqi@0 489 return false;
aoqi@0 490 }
aoqi@0 491 }
aoqi@0 492 return true;
aoqi@0 493 }
aoqi@0 494
aoqi@0 495 /**
aoqi@0 496 * Verify that a package pattern is valid.
aoqi@0 497 */
aoqi@0 498 private static void checkPattern(String s) throws ProblemException {
aoqi@0 499 // Package names like foo.bar.gamma are allowed, and
aoqi@0 500 // package names suffixed with .* like foo.bar.* are
aoqi@0 501 // also allowed.
aoqi@0 502 Pattern p = Pattern.compile("[a-zA-Z_]{1}[a-zA-Z0-9_]*(\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*)*(\\.\\*)?+");
aoqi@0 503 Matcher m = p.matcher(s);
aoqi@0 504 if (!m.matches()) {
aoqi@0 505 throw new ProblemException("The string \""+s+"\" is not a proper package name pattern.");
aoqi@0 506 }
aoqi@0 507 }
aoqi@0 508
aoqi@0 509 /**
aoqi@0 510 * Verify that a translate pattern is valid.
aoqi@0 511 */
aoqi@0 512 private static void checkTranslatePattern(String s) throws ProblemException {
aoqi@0 513 // .prop=com.sun.tools.javac.smart.CompileProperties
aoqi@0 514 // .idl=com.sun.corba.CompileIdl
aoqi@0 515 // .g3=antlr.CompileGrammar,debug=true
aoqi@0 516 Pattern p = Pattern.compile(
aoqi@0 517 "\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*=[a-z_]{1}[a-z0-9_]*(\\.[a-z_]{1}[a-z0-9_]*)*"+
aoqi@0 518 "(\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*)(,.*)?");
aoqi@0 519 Matcher m = p.matcher(s);
aoqi@0 520 if (!m.matches()) {
aoqi@0 521 throw new ProblemException("The string \""+s+"\" is not a proper translate pattern.");
aoqi@0 522 }
aoqi@0 523 }
aoqi@0 524
aoqi@0 525 /**
aoqi@0 526 * Verify that a copy pattern is valid.
aoqi@0 527 */
aoqi@0 528 private static void checkCopyPattern(String s) throws ProblemException {
aoqi@0 529 // .gif
aoqi@0 530 // .html
aoqi@0 531 Pattern p = Pattern.compile(
aoqi@0 532 "\\.[a-zA-Z_]{1}[a-zA-Z0-9_]*");
aoqi@0 533 Matcher m = p.matcher(s);
aoqi@0 534 if (!m.matches()) {
aoqi@0 535 throw new ProblemException("The string \""+s+"\" is not a proper suffix.");
aoqi@0 536 }
aoqi@0 537 }
aoqi@0 538
aoqi@0 539 /**
aoqi@0 540 * Verify that a source file name is valid.
aoqi@0 541 */
aoqi@0 542 private static void checkFilePattern(String s) throws ProblemException {
aoqi@0 543 // File names like foo/bar/gamma/Bar.java are allowed,
aoqi@0 544 // as well as /bar/jndi.properties as well as,
aoqi@0 545 // */bar/Foo.java
aoqi@0 546 Pattern p = null;
aoqi@0 547 if (File.separatorChar == '\\') {
aoqi@0 548 p = Pattern.compile("\\*?(.+\\\\)*.+");
aoqi@0 549 }
aoqi@0 550 else if (File.separatorChar == '/') {
aoqi@0 551 p = Pattern.compile("\\*?(.+/)*.+");
aoqi@0 552 } else {
aoqi@0 553 throw new ProblemException("This platform uses the unsupported "+File.separatorChar+
aoqi@0 554 " as file separator character. Please add support for it!");
aoqi@0 555 }
aoqi@0 556 Matcher m = p.matcher(s);
aoqi@0 557 if (!m.matches()) {
aoqi@0 558 throw new ProblemException("The string \""+s+"\" is not a proper file name.");
aoqi@0 559 }
aoqi@0 560 }
aoqi@0 561
aoqi@0 562 /**
aoqi@0 563 * Scan the arguments to find an option is used.
aoqi@0 564 */
aoqi@0 565 private static boolean hasOption(String[] args, String option) {
aoqi@0 566 for (String a : args) {
aoqi@0 567 if (a.equals(option)) return true;
aoqi@0 568 }
aoqi@0 569 return false;
aoqi@0 570 }
aoqi@0 571
aoqi@0 572 /**
aoqi@0 573 * Check if -implicit is supplied, if so check that it is none.
aoqi@0 574 * If -implicit is not supplied, supply -implicit:none
aoqi@0 575 * Only implicit:none is allowed because otherwise the multicore compilations
aoqi@0 576 * and dependency tracking will be tangled up.
aoqi@0 577 */
aoqi@0 578 private static String[] verifyImplicitOption(String[] args)
aoqi@0 579 throws ProblemException {
aoqi@0 580
aoqi@0 581 boolean foundImplicit = false;
aoqi@0 582 for (String a : args) {
aoqi@0 583 if (a.startsWith("-implicit:")) {
aoqi@0 584 foundImplicit = true;
aoqi@0 585 if (!a.equals("-implicit:none")) {
aoqi@0 586 throw new ProblemException("The only allowed setting for sjavac is -implicit:none, it is also the default.");
aoqi@0 587 }
aoqi@0 588 }
aoqi@0 589 }
aoqi@0 590 if (foundImplicit) {
aoqi@0 591 return args;
aoqi@0 592 }
aoqi@0 593 // -implicit:none not found lets add it.
aoqi@0 594 String[] newargs = new String[args.length+1];
aoqi@0 595 System.arraycopy(args,0, newargs, 0, args.length);
aoqi@0 596 newargs[args.length] = "-implicit:none";
aoqi@0 597 return newargs;
aoqi@0 598 }
aoqi@0 599
aoqi@0 600 /**
aoqi@0 601 * Rewrite a single option into something else.
aoqi@0 602 */
aoqi@0 603 private static void rewriteOptions(String[] args, String option, String new_option) {
aoqi@0 604 for (int i=0; i<args.length; ++i) {
aoqi@0 605 if (args[i].equals(option)) {
aoqi@0 606 args[i] = new_option;
aoqi@0 607 }
aoqi@0 608 }
aoqi@0 609 }
aoqi@0 610
aoqi@0 611 /**
aoqi@0 612 * Scan the arguments to find an option that specifies a directory.
aoqi@0 613 * Create the directory if necessary.
aoqi@0 614 */
aoqi@0 615 private static File findDirectoryOption(String[] args, String option, String name, boolean needed, boolean allow_dups, boolean create)
aoqi@0 616 throws ProblemException, ProblemException {
aoqi@0 617 File dir = null;
aoqi@0 618 for (int i = 0; i<args.length; ++i) {
aoqi@0 619 if (args[i].equals(option)) {
aoqi@0 620 if (dir != null) {
aoqi@0 621 throw new ProblemException("You have already specified the "+name+" dir!");
aoqi@0 622 }
aoqi@0 623 if (i+1 >= args.length) {
aoqi@0 624 throw new ProblemException("You have to specify a directory following "+option+".");
aoqi@0 625 }
aoqi@0 626 if (args[i+1].indexOf(File.pathSeparatorChar) != -1) {
aoqi@0 627 throw new ProblemException("You must only specify a single directory for "+option+".");
aoqi@0 628 }
aoqi@0 629 dir = new File(args[i+1]);
aoqi@0 630 if (!dir.exists()) {
aoqi@0 631 if (!create) {
aoqi@0 632 throw new ProblemException("This directory does not exist: "+dir.getPath());
aoqi@0 633 } else
aoqi@0 634 if (!makeSureExists(dir)) {
aoqi@0 635 throw new ProblemException("Cannot create directory "+dir.getPath());
aoqi@0 636 }
aoqi@0 637 }
aoqi@0 638 if (!dir.isDirectory()) {
aoqi@0 639 throw new ProblemException("\""+args[i+1]+"\" is not a directory.");
aoqi@0 640 }
aoqi@0 641 }
aoqi@0 642 }
aoqi@0 643 if (dir == null && needed) {
aoqi@0 644 throw new ProblemException("You have to specify "+option);
aoqi@0 645 }
aoqi@0 646 try {
aoqi@0 647 if (dir != null)
aoqi@0 648 return dir.getCanonicalFile();
aoqi@0 649 } catch (IOException e) {
aoqi@0 650 throw new ProblemException(""+e);
aoqi@0 651 }
aoqi@0 652 return null;
aoqi@0 653 }
aoqi@0 654
aoqi@0 655 /**
aoqi@0 656 * Option is followed by path.
aoqi@0 657 */
aoqi@0 658 private static boolean shouldBeFollowedByPath(String o) {
aoqi@0 659 return o.equals("-s") ||
aoqi@0 660 o.equals("-h") ||
aoqi@0 661 o.equals("-d") ||
aoqi@0 662 o.equals("-sourcepath") ||
aoqi@0 663 o.equals("-classpath") ||
aoqi@0 664 o.equals("-cp") ||
aoqi@0 665 o.equals("-bootclasspath") ||
aoqi@0 666 o.equals("-src");
aoqi@0 667 }
aoqi@0 668
aoqi@0 669 /**
aoqi@0 670 * Add -src before source root directories if not already there.
aoqi@0 671 */
aoqi@0 672 private static String[] addSrcBeforeDirectories(String[] args) {
aoqi@0 673 List<String> newargs = new ArrayList<String>();
aoqi@0 674 for (int i = 0; i<args.length; ++i) {
aoqi@0 675 File dir = new File(args[i]);
aoqi@0 676 if (dir.exists() && dir.isDirectory()) {
aoqi@0 677 if (i == 0 || !shouldBeFollowedByPath(args[i-1])) {
aoqi@0 678 newargs.add("-src");
aoqi@0 679 }
aoqi@0 680 }
aoqi@0 681 newargs.add(args[i]);
aoqi@0 682 }
aoqi@0 683 return newargs.toArray(new String[0]);
aoqi@0 684 }
aoqi@0 685
aoqi@0 686 /**
aoqi@0 687 * Check the -src options.
aoqi@0 688 */
aoqi@0 689 private static void checkSrcOption(String[] args)
aoqi@0 690 throws ProblemException {
aoqi@0 691 Set<File> dirs = new HashSet<File>();
aoqi@0 692 for (int i = 0; i<args.length; ++i) {
aoqi@0 693 if (args[i].equals("-src")) {
aoqi@0 694 if (i+1 >= args.length) {
aoqi@0 695 throw new ProblemException("You have to specify a directory following -src.");
aoqi@0 696 }
aoqi@0 697 StringTokenizer st = new StringTokenizer(args[i+1], File.pathSeparator);
aoqi@0 698 while (st.hasMoreElements()) {
aoqi@0 699 File dir = new File(st.nextToken());
aoqi@0 700 if (!dir.exists()) {
aoqi@0 701 throw new ProblemException("This directory does not exist: "+dir.getPath());
aoqi@0 702 }
aoqi@0 703 if (!dir.isDirectory()) {
aoqi@0 704 throw new ProblemException("\""+dir.getPath()+"\" is not a directory.");
aoqi@0 705 }
aoqi@0 706 if (dirs.contains(dir)) {
aoqi@0 707 throw new ProblemException("The src directory \""+dir.getPath()+"\" is specified more than once!");
aoqi@0 708 }
aoqi@0 709 dirs.add(dir);
aoqi@0 710 }
aoqi@0 711 }
aoqi@0 712 }
aoqi@0 713 if (dirs.isEmpty()) {
aoqi@0 714 throw new ProblemException("You have to specify -src.");
aoqi@0 715 }
aoqi@0 716 }
aoqi@0 717
aoqi@0 718 /**
aoqi@0 719 * Scan the arguments to find an option that specifies a file.
aoqi@0 720 */
aoqi@0 721 private static File findFileOption(String[] args, String option, String name, boolean needed)
aoqi@0 722 throws ProblemException, ProblemException {
aoqi@0 723 File file = null;
aoqi@0 724 for (int i = 0; i<args.length; ++i) {
aoqi@0 725 if (args[i].equals(option)) {
aoqi@0 726 if (file != null) {
aoqi@0 727 throw new ProblemException("You have already specified the "+name+" file!");
aoqi@0 728 }
aoqi@0 729 if (i+1 >= args.length) {
aoqi@0 730 throw new ProblemException("You have to specify a file following "+option+".");
aoqi@0 731 }
aoqi@0 732 file = new File(args[i+1]);
aoqi@0 733 if (file.isDirectory()) {
aoqi@0 734 throw new ProblemException("\""+args[i+1]+"\" is not a file.");
aoqi@0 735 }
aoqi@0 736 if (!file.exists() && needed) {
aoqi@0 737 throw new ProblemException("The file \""+args[i+1]+"\" does not exist.");
aoqi@0 738 }
aoqi@0 739
aoqi@0 740 }
aoqi@0 741 }
aoqi@0 742 if (file == null && needed) {
aoqi@0 743 throw new ProblemException("You have to specify "+option);
aoqi@0 744 }
aoqi@0 745 return file;
aoqi@0 746 }
aoqi@0 747
aoqi@0 748 /**
aoqi@0 749 * Look for a specific switch, return true if found.
aoqi@0 750 */
aoqi@0 751 public static boolean findBooleanOption(String[] args, String option) {
aoqi@0 752 for (int i = 0; i<args.length; ++i) {
aoqi@0 753 if (args[i].equals(option)) return true;
aoqi@0 754 }
aoqi@0 755 return false;
aoqi@0 756 }
aoqi@0 757
aoqi@0 758 /**
aoqi@0 759 * Scan the arguments to find an option that specifies a number.
aoqi@0 760 */
aoqi@0 761 public static int findNumberOption(String[] args, String option) {
aoqi@0 762 int rc = 0;
aoqi@0 763 for (int i = 0; i<args.length; ++i) {
aoqi@0 764 if (args[i].equals(option)) {
aoqi@0 765 if (args.length > i+1) {
aoqi@0 766 rc = Integer.parseInt(args[i+1]);
aoqi@0 767 }
aoqi@0 768 }
aoqi@0 769 }
aoqi@0 770 return rc;
aoqi@0 771 }
aoqi@0 772
aoqi@0 773 /**
aoqi@0 774 * Scan the arguments to find the option (-tr) that setup translation rules to java source
aoqi@0 775 * from different sources. For example: .properties are translated using CompileProperties
aoqi@0 776 * The found translators are stored as suffix rules.
aoqi@0 777 */
aoqi@0 778 private static void findTranslateOptions(String[] args, Map<String,Transformer> suffix_rules)
aoqi@0 779 throws ProblemException, ProblemException {
aoqi@0 780
aoqi@0 781 for (int i = 0; i<args.length; ++i) {
aoqi@0 782 if (args[i].equals("-tr")) {
aoqi@0 783 if (i+1 >= args.length) {
aoqi@0 784 throw new ProblemException("You have to specify a translate rule following -tr.");
aoqi@0 785 }
aoqi@0 786 String s = args[i+1];
aoqi@0 787 checkTranslatePattern(s);
aoqi@0 788 int ep = s.indexOf("=");
aoqi@0 789 String suffix = s.substring(0,ep);
aoqi@0 790 String classname = s.substring(ep+1);
aoqi@0 791 if (suffix_rules.get(suffix) != null) {
aoqi@0 792 throw new ProblemException("You have already specified a "+
aoqi@0 793 "rule for the suffix "+suffix);
aoqi@0 794 }
aoqi@0 795 if (s.equals(".class")) {
aoqi@0 796 throw new ProblemException("You cannot have a translator for .class files!");
aoqi@0 797 }
aoqi@0 798 if (s.equals(".java")) {
aoqi@0 799 throw new ProblemException("You cannot have a translator for .java files!");
aoqi@0 800 }
aoqi@0 801 String extra = null;
aoqi@0 802 int exp = classname.indexOf(",");
aoqi@0 803 if (exp != -1) {
aoqi@0 804 extra = classname.substring(exp+1);
aoqi@0 805 classname = classname.substring(0,exp);
aoqi@0 806 }
aoqi@0 807 try {
aoqi@0 808 Class<?> cl = Class.forName(classname);
aoqi@0 809 Transformer t = (Transformer)cl.newInstance();
aoqi@0 810 t.setExtra(extra);
aoqi@0 811 suffix_rules.put(suffix, t);
aoqi@0 812 }
aoqi@0 813 catch (Exception e) {
aoqi@0 814 throw new ProblemException("Cannot use "+classname+" as a translator!");
aoqi@0 815 }
aoqi@0 816 }
aoqi@0 817 }
aoqi@0 818 }
aoqi@0 819
aoqi@0 820 /**
aoqi@0 821 * Scan the arguments to find the option (-copy) that setup copying rules into the bin dir.
aoqi@0 822 * For example: -copy .html
aoqi@0 823 * The found copiers are stored as suffix rules as well. No translation is done, just copying.
aoqi@0 824 */
aoqi@0 825 private void findCopyOptions(String[] args, Map<String,Transformer> suffix_rules)
aoqi@0 826 throws ProblemException, ProblemException {
aoqi@0 827
aoqi@0 828 for (int i = 0; i<args.length; ++i) {
aoqi@0 829 if (args[i].equals("-copy")) {
aoqi@0 830 if (i+1 >= args.length) {
aoqi@0 831 throw new ProblemException("You have to specify a translate rule following -tr.");
aoqi@0 832 }
aoqi@0 833 String s = args[i+1];
aoqi@0 834 checkCopyPattern(s);
aoqi@0 835 if (suffix_rules.get(s) != null) {
aoqi@0 836 throw new ProblemException("You have already specified a "+
aoqi@0 837 "rule for the suffix "+s);
aoqi@0 838 }
aoqi@0 839 if (s.equals(".class")) {
aoqi@0 840 throw new ProblemException("You cannot have a copy rule for .class files!");
aoqi@0 841 }
aoqi@0 842 if (s.equals(".java")) {
aoqi@0 843 throw new ProblemException("You cannot have a copy rule for .java files!");
aoqi@0 844 }
aoqi@0 845 suffix_rules.put(s, javac_state.getCopier());
aoqi@0 846 }
aoqi@0 847 }
aoqi@0 848 }
aoqi@0 849
aoqi@0 850 /**
aoqi@0 851 * Rewrite a / separated path into \ separated, but only
aoqi@0 852 * if we are running on a platform were File.separatorChar=='\', ie winapi.
aoqi@0 853 */
aoqi@0 854 private String fixupSeparator(String p) {
aoqi@0 855 if (File.separatorChar == '/') return p;
aoqi@0 856 return p.replaceAll("/", "\\\\");
aoqi@0 857 }
aoqi@0 858
aoqi@0 859 /**
aoqi@0 860 * Scan the arguments for -i -x -xf -if followed by the option
aoqi@0 861 * -src, -sourcepath, -modulepath or -classpath and produce a map of all the
aoqi@0 862 * files to referenced for that particular option.
aoqi@0 863 *
aoqi@0 864 * Store the found sources and the found modules in the supplied maps.
aoqi@0 865 */
aoqi@0 866 private boolean findFiles(String[] args, String option, Set<String> suffixes,
aoqi@0 867 Map<String,Source> found_files, Map<String, Module> found_modules,
aoqi@0 868 Module current_module, boolean inLinksrc)
aoqi@0 869 throws ProblemException, ProblemException
aoqi@0 870 {
aoqi@0 871 // Track which source roots, source path roots and class path roots have been added.
aoqi@0 872 Set<File> roots = new HashSet<File>();
aoqi@0 873 // Track the current set of package includes,excludes as well as excluded source files,
aoqi@0 874 // to be used in the next -src/-sourcepath/-classpath
aoqi@0 875 List<String> includes = new LinkedList<String>();
aoqi@0 876 List<String> excludes = new LinkedList<String>();
aoqi@0 877 List<String> excludefiles = new LinkedList<String>();
aoqi@0 878 List<String> includefiles = new LinkedList<String>();
aoqi@0 879 // This include is used to find all modules in the source.
aoqi@0 880 List<String> moduleinfo = new LinkedList<String>();
aoqi@0 881 moduleinfo.add("module-info.java");
aoqi@0 882
aoqi@0 883 for (int i = 0; i<args.length; ++i) {
aoqi@0 884 if (args[i].equals("-i")) {
aoqi@0 885 if (i+1 >= args.length) {
aoqi@0 886 throw new ProblemException("You have to specify a package pattern following -i");
aoqi@0 887 }
aoqi@0 888 String incl = args[i+1];
aoqi@0 889 checkPattern(incl);
aoqi@0 890 includes.add(incl);
aoqi@0 891 }
aoqi@0 892 if (args[i].equals("-x")) {
aoqi@0 893 if (i+1 >= args.length) {
aoqi@0 894 throw new ProblemException("You have to specify a package pattern following -x");
aoqi@0 895 }
aoqi@0 896 String excl = args[i+1];
aoqi@0 897 checkPattern(excl);
aoqi@0 898 excludes.add(excl);
aoqi@0 899 }
aoqi@0 900 if (args[i].equals("-xf")) {
aoqi@0 901 if (i+1 >= args.length) {
aoqi@0 902 throw new ProblemException("You have to specify a file following -xf");
aoqi@0 903 }
aoqi@0 904 String exclf = args[i+1];
aoqi@0 905 checkFilePattern(exclf);
aoqi@0 906 exclf = Util.normalizeDriveLetter(exclf);
aoqi@0 907 excludefiles.add(fixupSeparator(exclf));
aoqi@0 908 }
aoqi@0 909 if (args[i].equals("-if")) {
aoqi@0 910 if (i+1 >= args.length) {
aoqi@0 911 throw new ProblemException("You have to specify a file following -xf");
aoqi@0 912 }
aoqi@0 913 String inclf = args[i+1];
aoqi@0 914 checkFilePattern(inclf);
aoqi@0 915 inclf = Util.normalizeDriveLetter(inclf);
aoqi@0 916 includefiles.add(fixupSeparator(inclf));
aoqi@0 917 }
aoqi@0 918 if (args[i].equals(option)) {
aoqi@0 919 if (i+1 >= args.length) {
aoqi@0 920 throw new ProblemException("You have to specify a directory following "+option);
aoqi@0 921 }
aoqi@0 922 String[] root_dirs = args[i+1].split(File.pathSeparator);
aoqi@0 923 for (String r : root_dirs) {
aoqi@0 924 File root = new File(r);
aoqi@0 925 if (!root.isDirectory()) {
aoqi@0 926 throw new ProblemException("\""+r+"\" is not a directory.");
aoqi@0 927 }
aoqi@0 928 try {
aoqi@0 929 root = root.getCanonicalFile();
aoqi@0 930 } catch (IOException e) {
aoqi@0 931 throw new ProblemException(""+e);
aoqi@0 932 }
aoqi@0 933 if (roots.contains(root)) {
aoqi@0 934 throw new ProblemException("\""+r+"\" has already been used for "+option);
aoqi@0 935 }
aoqi@0 936 if (root.equals(bin_dir)) {
aoqi@0 937 throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -d");
aoqi@0 938 }
aoqi@0 939 if (root.equals(gensrc_dir)) {
aoqi@0 940 throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -s");
aoqi@0 941 }
aoqi@0 942 if (root.equals(header_dir)) {
aoqi@0 943 throw new ProblemException("\""+r+"\" cannot be used both for "+option+" and -h");
aoqi@0 944 }
aoqi@0 945 roots.add(root);
aoqi@0 946 Source.scanRoot(root, suffixes, excludes, includes, excludefiles, includefiles,
aoqi@0 947 found_files, found_modules, current_module,
aoqi@0 948 findBooleanOption(args, "--permit-sources-without-package"),
aoqi@0 949 false, inLinksrc);
aoqi@0 950 }
aoqi@0 951 }
aoqi@0 952 if (args[i].equals("-src") ||
aoqi@0 953 args[i].equals("-sourcepath") ||
aoqi@0 954 args[i].equals("-modulepath") ||
aoqi@0 955 args[i].equals("-classpath") ||
aoqi@0 956 args[i].equals("-cp"))
aoqi@0 957 {
aoqi@0 958 // Reset the includes,excludes and excludefiles after they have been used.
aoqi@0 959 includes = new LinkedList<String>();
aoqi@0 960 excludes = new LinkedList<String>();
aoqi@0 961 excludefiles = new LinkedList<String>();
aoqi@0 962 includefiles = new LinkedList<String>();
aoqi@0 963 }
aoqi@0 964 }
aoqi@0 965 return true;
aoqi@0 966 }
aoqi@0 967
aoqi@0 968 }
aoqi@0 969

mercurial