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

mercurial