Options.java revision 2981:d1e5707cd4eb
11592Srgrimes/* 21592Srgrimes * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. 31592Srgrimes * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 41592Srgrimes * 51592Srgrimes * This code is free software; you can redistribute it and/or modify it 61592Srgrimes * under the terms of the GNU General Public License version 2 only, as 71592Srgrimes * published by the Free Software Foundation. Oracle designates this 81592Srgrimes * particular file as subject to the "Classpath" exception as provided 91592Srgrimes * by Oracle in the LICENSE file that accompanied this code. 101592Srgrimes * 111592Srgrimes * This code is distributed in the hope that it will be useful, but WITHOUT 121592Srgrimes * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 131592Srgrimes * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 141592Srgrimes * version 2 for more details (a copy is included in the LICENSE file that 151592Srgrimes * accompanied this code). 161592Srgrimes * 171592Srgrimes * You should have received a copy of the GNU General Public License version 181592Srgrimes * 2 along with this work; if not, write to the Free Software Foundation, 191592Srgrimes * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 201592Srgrimes * 211592Srgrimes * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 221592Srgrimes * or visit www.oracle.com if you need additional information or have any 231592Srgrimes * questions. 241592Srgrimes */ 251592Srgrimes 261592Srgrimespackage com.sun.tools.sjavac.options; 271592Srgrimes 281592Srgrimesimport java.nio.file.Path; 291592Srgrimesimport java.util.ArrayList; 301592Srgrimesimport java.util.Arrays; 311592Srgrimesimport java.util.Collection; 321592Srgrimesimport java.util.HashMap; 331592Srgrimesimport java.util.List; 341592Srgrimesimport java.util.Map; 351592Srgrimesimport java.util.Set; 361592Srgrimesimport java.util.HashSet; 371592Srgrimes 381592Srgrimesimport com.sun.tools.sjavac.Transformer; 391592Srgrimesimport com.sun.tools.sjavac.Util; 401592Srgrimes 411592Srgrimes/** 421592Srgrimes * Instances of this class represent values for sjavac command line options. 431592Srgrimes * 4431329Scharnier * <p><b>This is NOT part of any supported API. 451592Srgrimes * If you write code that depends on this, you do so at your own risk. 4631329Scharnier * This code and its internal interfaces are subject to change or 4731329Scharnier * deletion without notice.</b> 4850476Speter */ 491592Srgrimespublic class Options { 501592Srgrimes 511592Srgrimes // Output directories 521592Srgrimes private Path destDir, genSrcDir, headerDir, stateDir; 531592Srgrimes 541592Srgrimes // Input directories 551592Srgrimes private List<SourceLocation> sources = new ArrayList<>(); 561592Srgrimes private List<SourceLocation> sourceSearchPaths = new ArrayList<>(); 571592Srgrimes private List<SourceLocation> classSearchPaths = new ArrayList<>(); 581592Srgrimes private List<SourceLocation> moduleSearchPaths = new ArrayList<>(); 591592Srgrimes 601592Srgrimes private String logLevel = "info"; 6192090Smaxim 6292272Smaxim private Set<String> permitted_artifacts = new HashSet<>(); 6392090Smaxim private boolean permitUnidentifiedArtifacts = false; 6456668Sshin private boolean permitSourcesInDefaultPackage = false; 651592Srgrimes 661592Srgrimes private Path sourceReferenceList; 671592Srgrimes private int numCores = 4; 681592Srgrimes private String implicitPolicy = "none"; 691592Srgrimes private List<String> javacArgs = new ArrayList<>(); 701592Srgrimes 711592Srgrimes private Map<String, Transformer> trRules = new HashMap<>(); 721592Srgrimes 731592Srgrimes private boolean startServer = false; 741592Srgrimes 75109380Syar // Server configuration string 761592Srgrimes private String serverConf; 7756668Sshin 78110037Syar /** Get the policy for implicit classes */ 791592Srgrimes public String getImplicitPolicy() { 801592Srgrimes return implicitPolicy; 811592Srgrimes } 82110036Syar 8317435Spst /** Get the path for generated sources (or null if no such path is set) */ 841592Srgrimes public Path getGenSrcDir() { 851592Srgrimes return genSrcDir; 861592Srgrimes } 8776096Smarkm 881592Srgrimes /** Get the path for the destination directory */ 891592Srgrimes public Path getDestDir() { 901592Srgrimes return destDir; 9127650Sdavidn } 921592Srgrimes 931592Srgrimes /** Get the path for the header directory (or null if no such path is set) */ 941592Srgrimes public Path getHeaderDir() { 9570102Sphk return headerDir; 9670102Sphk } 9782460Snik 9882796Ssheldonh /** Get the path for the state directory, defaults to destDir. */ 99100684Syar public Path getStateDir() { 1001592Srgrimes return stateDir != null ? stateDir : destDir; 1011592Srgrimes } 1021592Srgrimes 1031592Srgrimes /** Get all source locations for files to be compiled */ 1041592Srgrimes public List<SourceLocation> getSources() { 1051592Srgrimes return sources; 10689935Syar } 1071592Srgrimes 10888935Sdwmalone /** 1091592Srgrimes * Get all paths to search for classes in .java format. (Java-files in 11056668Sshin * found here should not be compiled. 11156668Sshin */ 1121592Srgrimes public List<SourceLocation> getSourceSearchPaths() { 1131592Srgrimes return sourceSearchPaths; 1141592Srgrimes } 11592272Smaxim 11692272Smaxim /** Get all paths to search for classes in. */ 11792272Smaxim public List<SourceLocation> getClassSearchPath() { 11892272Smaxim return classSearchPaths; 1191592Srgrimes } 1201592Srgrimes 1211592Srgrimes /** Get all paths to search for modules in. */ 1221592Srgrimes public List<SourceLocation> getModuleSearchPaths() { 1231592Srgrimes return moduleSearchPaths; 1241592Srgrimes } 12556668Sshin 1261592Srgrimes /** Get the log level. */ 1271592Srgrimes public String getLogLevel() { 1281592Srgrimes return logLevel; 1291592Srgrimes } 1301592Srgrimes 1311592Srgrimes /** Returns true iff the artifact is permitted in the output dir. */ 1321592Srgrimes public boolean isUnidentifiedArtifactPermitted(String f) { 1331592Srgrimes return permitted_artifacts.contains(f); 1341592Srgrimes } 1351592Srgrimes 13656668Sshin /** Returns true iff artifacts in the output directories should be kept, 1371592Srgrimes * even if they would not be generated in a clean build. */ 13875535Sphk public boolean areUnidentifiedArtifactsPermitted() { 1391592Srgrimes return permitUnidentifiedArtifacts; 140102565Syar } 1411592Srgrimes 1421592Srgrimes /** Returns true iff sources in the default package should be permitted. */ 14392272Smaxim public boolean isDefaultPackagePermitted() { 1441592Srgrimes return permitSourcesInDefaultPackage; 14592272Smaxim } 14692272Smaxim 14792272Smaxim /** Get the path to the list of reference sources (or null if none is set) */ 14875567Speter public Path getSourceReferenceList() { 149102565Syar return sourceReferenceList; 1501592Srgrimes } 1511592Srgrimes 1521592Srgrimes /** Get the number of cores to be used by sjavac */ 1531592Srgrimes public int getNumCores() { 1541592Srgrimes return numCores; 1551592Srgrimes } 1561592Srgrimes 1571592Srgrimes /** Returns all arguments relevant to javac but irrelevant to sjavac. */ 1581592Srgrimes public List<String> getJavacArgs() { 15988935Sdwmalone return javacArgs; 16088935Sdwmalone } 1611592Srgrimes 1621592Srgrimes /** 1631592Srgrimes * Get a map which maps suffixes to transformers (for example 1641592Srgrimes * ".java" {@literal ->} CompileJavaPackages) 1651592Srgrimes */ 1661592Srgrimes public Map<String, Transformer> getTranslationRules() { 1671592Srgrimes return trRules; 1681592Srgrimes } 1691592Srgrimes 1701592Srgrimes /** Return true iff a new server should be started */ 1711592Srgrimes public boolean startServerFlag() { 1721592Srgrimes return startServer; 1731592Srgrimes } 1741592Srgrimes 1751592Srgrimes /** Return the server configuration string. */ 1761592Srgrimes public String getServerConf() { 1771592Srgrimes return serverConf; 17875556Sgreen } 17975556Sgreen 18075556Sgreen /** 18175556Sgreen * Parses the given argument array and returns a corresponding Options 18217433Spst * instance. 1831592Srgrimes */ 18456668Sshin public static Options parseArgs(String... args) { 18556668Sshin Options options = new Options(); 18656668Sshin options.new ArgDecoderOptionHelper().traverse(args); 18756668Sshin return options; 18856668Sshin } 18956668Sshin 19056668Sshin /** Returns true iff a .java file is among the javac arguments */ 19156668Sshin public boolean isJavaFilesAmongJavacArgs() { 19256668Sshin for (String javacArg : javacArgs) 19356668Sshin if (javacArg.endsWith(".java")) 19456668Sshin return true; 19556668Sshin return false; 19656668Sshin } 19756668Sshin 19856668Sshin /** 19956668Sshin * Returns a string representation of the options that affect the result of 20056668Sshin * the compilation. (Used for saving the state of the options used in a 20156668Sshin * previous compile.) 20256668Sshin */ 203132925Syar public String getStateArgsString() { 20456668Sshin 20556668Sshin // Local utility class for collecting the arguments 20656668Sshin class StateArgs { 20756668Sshin 20856668Sshin private List<String> args = new ArrayList<>(); 20956668Sshin 21056668Sshin void addArg(Option opt) { 21156668Sshin args.add(opt.arg); 21256668Sshin } 21356668Sshin 21456668Sshin void addArg(Option opt, Object val) { 21556668Sshin addArg(opt); 21656668Sshin args.add(val.toString()); 21756668Sshin } 21856668Sshin 21956668Sshin void addSourceLocations(Option opt, List<SourceLocation> locs) { 22056668Sshin for (SourceLocation sl : locs) { 22156668Sshin for (String pkg : sl.includes) addArg(Option.I, pkg); 22256668Sshin for (String pkg : sl.excludes) addArg(Option.X, pkg); 22356668Sshin for (String f : sl.excludedFiles) addArg(Option.XF, f); 22456668Sshin for (String f : sl.includedFiles) addArg(Option.IF, f); 225132925Syar addArg(opt, sl.getPath()); 22656668Sshin } 22756668Sshin } 22856668Sshin 22956668Sshin String getResult() { 23056668Sshin String result = ""; 23156668Sshin for (String s : args) 23256668Sshin result += s + " "; 23356668Sshin return result.trim(); 23456668Sshin } 23556668Sshin 23656668Sshin public void addAll(Collection<String> toAdd) { 23756668Sshin args.addAll(toAdd); 23856668Sshin } 23956668Sshin } 24056668Sshin 24156668Sshin StateArgs args = new StateArgs(); 24256668Sshin 24356668Sshin // Directories 24456668Sshin if (genSrcDir != null) 24556668Sshin args.addArg(Option.S, genSrcDir.normalize()); 24676096Smarkm 24756668Sshin if (headerDir != null) 24856668Sshin args.addArg(Option.H, headerDir.normalize()); 24976096Smarkm 25056668Sshin if (destDir != null) 25156668Sshin args.addArg(Option.D, destDir.normalize()); 25256668Sshin 25356668Sshin if (stateDir != null) 25456668Sshin args.addArg(Option.STATE_DIR, stateDir.normalize()); 25556668Sshin 25656668Sshin // Source roots 25756668Sshin args.addSourceLocations(Option.SRC, sources); 25856668Sshin args.addSourceLocations(Option.SOURCEPATH, sourceSearchPaths); 25956668Sshin args.addSourceLocations(Option.CLASSPATH, classSearchPaths); 26056668Sshin args.addSourceLocations(Option.MODULEPATH, moduleSearchPaths); 26156668Sshin 26256668Sshin // Boolean options 26356668Sshin if (permitSourcesInDefaultPackage) 26417433Spst args.addArg(Option.PERMIT_SOURCES_WITHOUT_PACKAGE); 26556668Sshin 26617433Spst for (String f : permitted_artifacts) { 26756668Sshin args.addArg(Option.PERMIT_ARTIFACT, f); 26856668Sshin } 26976096Smarkm 27056668Sshin if (permitUnidentifiedArtifacts) 27156668Sshin args.addArg(Option.PERMIT_UNIDENTIFIED_ARTIFACTS); 2721592Srgrimes 27356668Sshin // Translation rules 27456668Sshin for (Map.Entry<String, Transformer> tr : trRules.entrySet()) { 27556668Sshin String val = tr.getKey() + "=" + tr.getValue().getClass().getName(); 27656668Sshin args.addArg(Option.TR, val); 27756668Sshin } 27856668Sshin 27956668Sshin // Javac args 28056668Sshin args.addAll(javacArgs); 28156668Sshin 28256668Sshin return args.getResult(); 28356668Sshin } 28456668Sshin 28556668Sshin 28656668Sshin /** Extract the arguments to be passed on to javac. */ 28756668Sshin public String[] prepJavacArgs() { 28856668Sshin List<String> args = new ArrayList<>(); 28956668Sshin 29056668Sshin // Output directories 29156668Sshin args.add("-d"); 29256668Sshin args.add(destDir.toString()); 29356668Sshin 29456668Sshin if (getGenSrcDir() != null) { 29556668Sshin args.add("-s"); 29656668Sshin args.add(genSrcDir.toString()); 29756668Sshin } 29856668Sshin 29956668Sshin if (headerDir != null) { 30056668Sshin args.add("-h"); 30156668Sshin args.add(headerDir.toString()); 30256668Sshin } 30356668Sshin 30456668Sshin // Prep sourcepath 30556668Sshin List<SourceLocation> sourcepath = new ArrayList<>(); 30656668Sshin sourcepath.addAll(sources); 30756668Sshin sourcepath.addAll(sourceSearchPaths); 30856668Sshin if (sourcepath.size() > 0) { 30956668Sshin args.add("-sourcepath"); 31056668Sshin args.add(concatenateSourceLocations(sourcepath)); 31156668Sshin } 31256668Sshin 31356668Sshin // Prep classpath 31456668Sshin if (classSearchPaths.size() > 0) { 31556668Sshin args.add("-classpath"); 31656668Sshin args.add(concatenateSourceLocations(classSearchPaths)); 31756668Sshin } 31856668Sshin 31956668Sshin // Enable dependency generation 32056668Sshin args.add("-XDcompletionDeps=source,class"); 32156668Sshin 32256668Sshin // This can't be anything but 'none'. Enforced by sjavac main method. 32356668Sshin args.add("-implicit:" + implicitPolicy); 32456668Sshin 32588935Sdwmalone // If this option is not used, Object for instance is erroneously 32688935Sdwmalone // picked up from PLATFORM_CLASS_PATH instead of CLASS_PATH. 3271592Srgrimes // 32817433Spst // Discussing this further led to the decision of letting bootclasspath 3291592Srgrimes // be a dummy (empty) directory when building the JDK. 33056668Sshin //args.add("-XXuserPathsFirst"); 33156668Sshin 33256668Sshin // Append javac-options (i.e. pass through options not recognized by 33317433Spst // sjavac to javac.) 3341592Srgrimes args.addAll(javacArgs); 33556668Sshin 33656668Sshin return args.toArray(new String[args.size()]); 33756668Sshin } 33856668Sshin 33956668Sshin // Helper method to join a list of source locations separated by 34056668Sshin // File.pathSeparator 34156668Sshin private static String concatenateSourceLocations(List<SourceLocation> locs) { 34270102Sphk String s = ""; 34356668Sshin for (SourceLocation loc : locs) 34456668Sshin s += (s.isEmpty() ? "" : java.io.File.pathSeparator) + loc.getPath(); 34556668Sshin return s; 34692272Smaxim } 34756668Sshin 34856668Sshin // OptionHelper that records the traversed options in this Options instance. 34956668Sshin private class ArgDecoderOptionHelper extends OptionHelper { 35056668Sshin 35156668Sshin List<String> includes, excludes, includeFiles, excludeFiles; 35256668Sshin { 35356668Sshin resetFilters(); 35456668Sshin } 35556668Sshin 35656668Sshin boolean headerProvided = false; 35756668Sshin boolean genSrcProvided = false; 35856668Sshin boolean stateProvided = false; 35956668Sshin 36056668Sshin @Override 36156668Sshin public void reportError(String msg) { 36270102Sphk throw new IllegalArgumentException(msg); 36356668Sshin } 36456668Sshin 36556668Sshin @Override 36656668Sshin public void sourceRoots(List<Path> paths) { 36756668Sshin sources.addAll(createSourceLocations(paths)); 36856668Sshin } 36956668Sshin 37070102Sphk @Override 37156668Sshin public void exclude(String exclPattern) { 37256668Sshin exclPattern = Util.normalizeDriveLetter(exclPattern); 37356668Sshin excludes.add(exclPattern); 37456668Sshin } 37571278Sjedgar 3761592Srgrimes @Override 37771278Sjedgar public void include(String inclPattern) { 37871278Sjedgar inclPattern = Util.normalizeDriveLetter(inclPattern); 3791592Srgrimes includes.add(inclPattern); 38071278Sjedgar } 38171278Sjedgar 38271278Sjedgar @Override 38371278Sjedgar public void excludeFile(String exclFilePattern) { 38471278Sjedgar exclFilePattern = Util.normalizeDriveLetter(exclFilePattern); 38571278Sjedgar excludeFiles.add(exclFilePattern); 38671278Sjedgar } 38771278Sjedgar 3881592Srgrimes @Override 38971278Sjedgar public void includeFile(String inclFilePattern) { 39071278Sjedgar inclFilePattern = Util.normalizeDriveLetter(inclFilePattern); 39171278Sjedgar includeFiles.add(inclFilePattern); 3921592Srgrimes } 39371278Sjedgar 39471278Sjedgar @Override 39571278Sjedgar public void addTransformer(String suffix, Transformer tr) { 39671278Sjedgar if (trRules.containsKey(suffix)) { 3971592Srgrimes reportError("More than one transformer specified for " + 39871278Sjedgar "suffix " + suffix + "."); 399103949Smike return; 40071278Sjedgar } 40171278Sjedgar trRules.put(suffix, tr); 40271278Sjedgar } 40371278Sjedgar 40471278Sjedgar @Override 40571278Sjedgar public void sourcepath(List<Path> paths) { 406103949Smike sourceSearchPaths.addAll(createSourceLocations(paths)); 407103949Smike } 408103949Smike 40971278Sjedgar @Override 4101592Srgrimes public void modulepath(List<Path> paths) { 4111592Srgrimes moduleSearchPaths.addAll(createSourceLocations(paths)); 41271278Sjedgar } 4131592Srgrimes 41471278Sjedgar @Override 41571278Sjedgar public void classpath(List<Path> paths) { 4161592Srgrimes classSearchPaths.addAll(createSourceLocations(paths)); 41771278Sjedgar } 41871278Sjedgar 41971278Sjedgar @Override 4201592Srgrimes public void numCores(int n) { 42171278Sjedgar numCores = n; 42271278Sjedgar } 42371278Sjedgar 4241592Srgrimes @Override 4251592Srgrimes public void logLevel(String level) { 42671278Sjedgar logLevel = level; 4271592Srgrimes } 42871278Sjedgar 42971278Sjedgar @Override 4301592Srgrimes public void compareFoundSources(Path referenceList) { 43171278Sjedgar sourceReferenceList = referenceList; 43271278Sjedgar } 43371278Sjedgar 43471278Sjedgar @Override 43571278Sjedgar public void permitArtifact(String f) { 43671278Sjedgar permitted_artifacts.add(f); 43771278Sjedgar } 4381592Srgrimes 4391592Srgrimes @Override 44071278Sjedgar public void permitUnidentifiedArtifacts() { 4411592Srgrimes permitUnidentifiedArtifacts = true; 44271278Sjedgar } 44371278Sjedgar 44471278Sjedgar @Override 4451592Srgrimes public void permitDefaultPackage() { 44671278Sjedgar permitSourcesInDefaultPackage = true; 4471592Srgrimes } 44871278Sjedgar 44971278Sjedgar @Override 45071278Sjedgar public void serverConf(String conf) { 4511592Srgrimes if (serverConf != null) 4521592Srgrimes reportError("Can not specify more than one server configuration."); 4531592Srgrimes else 45482796Ssheldonh serverConf = conf; 45582460Snik } 45682460Snik 4571592Srgrimes @Override 45882460Snik public void implicit(String policy) { 4591592Srgrimes implicitPolicy = policy; 4601592Srgrimes } 4611592Srgrimes 46270102Sphk @Override 4631592Srgrimes public void startServerConf(String conf) { 4641592Srgrimes if (serverConf != null) 4651592Srgrimes reportError("Can not specify more than one server configuration."); 4661592Srgrimes else { 4671592Srgrimes startServer = true; 4681592Srgrimes serverConf = conf; 46970102Sphk } 4701592Srgrimes } 4711592Srgrimes 4721592Srgrimes @Override 4731592Srgrimes public void javacArg(String... arg) { 4741592Srgrimes javacArgs.addAll(Arrays.asList(arg)); 4751592Srgrimes } 4761592Srgrimes 4771592Srgrimes @Override 4781592Srgrimes public void destDir(Path dir) { 4791592Srgrimes if (destDir != null) { 4801592Srgrimes reportError("Destination directory already specified."); 481101395Syar return; 4821592Srgrimes } 483101395Syar destDir = dir.toAbsolutePath(); 4841592Srgrimes } 485101395Syar 4861592Srgrimes @Override 4871592Srgrimes public void generatedSourcesDir(Path dir) { 4881592Srgrimes if (genSrcProvided) { 4891592Srgrimes reportError("Directory for generated sources already specified."); 490109380Syar return; 4911592Srgrimes } 49275567Speter genSrcProvided = true; 4931592Srgrimes genSrcDir = dir.toAbsolutePath(); 494101395Syar } 495109380Syar 496101395Syar @Override 4971592Srgrimes public void headerDir(Path dir) { 4981592Srgrimes if (headerProvided) { 4991592Srgrimes reportError("Header directory already specified."); 5001592Srgrimes return; 5011592Srgrimes } 5021592Srgrimes headerProvided = true; 5031592Srgrimes headerDir = dir.toAbsolutePath(); 5041592Srgrimes } 50571278Sjedgar 5061592Srgrimes @Override 50771278Sjedgar public void stateDir(Path dir) { 50871278Sjedgar if (stateProvided) { 50971278Sjedgar reportError("State directory already specified."); 5101592Srgrimes return; 51170102Sphk } 5121592Srgrimes stateProvided = true; 5131592Srgrimes stateDir = dir.toAbsolutePath(); 5141592Srgrimes } 5151592Srgrimes 5161592Srgrimes private List<SourceLocation> createSourceLocations(List<Path> paths) { 5171592Srgrimes List<SourceLocation> result = new ArrayList<>(); 51870102Sphk for (Path path : paths) { 5191592Srgrimes result.add(new SourceLocation( 520101379Syar path, 52117433Spst includes, 52217433Spst excludes, 52317433Spst includeFiles, 52417433Spst excludeFiles)); 52517433Spst } 52617433Spst resetFilters(); 52717433Spst return result; 5281592Srgrimes } 529101379Syar 530101379Syar private void resetFilters() { 5311592Srgrimes includes = new ArrayList<>(); 53271278Sjedgar excludes = new ArrayList<>(); 5331592Srgrimes includeFiles = new ArrayList<>(); 53471278Sjedgar excludeFiles = new ArrayList<>(); 53571278Sjedgar } 5361592Srgrimes } 5371592Srgrimes 5381592Srgrimes} 53969234Sdanny