Option.java revision 3474:dcb234002184
1228753Smm/* 2228753Smm * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. 3313570Smm * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4228753Smm * 5228753Smm * This code is free software; you can redistribute it and/or modify it 6228753Smm * under the terms of the GNU General Public License version 2 only, as 7228753Smm * published by the Free Software Foundation. Oracle designates this 8228753Smm * particular file as subject to the "Classpath" exception as provided 9228753Smm * by Oracle in the LICENSE file that accompanied this code. 10228753Smm * 11228753Smm * This code is distributed in the hope that it will be useful, but WITHOUT 12228753Smm * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13228753Smm * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14228753Smm * version 2 for more details (a copy is included in the LICENSE file that 15228753Smm * accompanied this code). 16228753Smm * 17228753Smm * You should have received a copy of the GNU General Public License version 18228753Smm * 2 along with this work; if not, write to the Free Software Foundation, 19228753Smm * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20228753Smm * 21228753Smm * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22228753Smm * or visit www.oracle.com if you need additional information or have any 23228753Smm * questions. 24228753Smm */ 25228753Smm 26228753Smmpackage com.sun.tools.sjavac.options; 27228763Smm 28228753Smmimport java.io.File; 29228753Smmimport java.nio.file.Path; 30228753Smmimport java.nio.file.Paths; 31313570Smmimport java.util.ArrayList; 32228753Smmimport java.util.List; 33228753Smmimport java.util.regex.Matcher; 34228753Smmimport java.util.regex.Pattern; 35228753Smm 36228753Smmimport com.sun.tools.sjavac.CopyFile; 37228753Smmimport com.sun.tools.sjavac.Transformer; 38228753Smm 39313570Smm 40228753Smm/** 41228753Smm * Sjavac options can be classified as: 42228753Smm * 43228753Smm * (1) relevant only for sjavac, such as --server 44228753Smm * (2) relevant for sjavac and javac, such as -d, or 45228753Smm * (3) relevant only for javac, such as -g. 46228753Smm * 47228753Smm * This enum represents all options from (1) and (2). Note that instances of 48313570Smm * this enum only entail static information about the option. For storage of 49228753Smm * option values, refer to com.sun.tools.sjavac.options.Options. 50228753Smm * 51228753Smm * <p><b>This is NOT part of any supported API. 52228753Smm * If you write code that depends on this, you do so at your own risk. 53228753Smm * This code and its internal interfaces are subject to change or 54228753Smm * deletion without notice.</b> 55228753Smm */ 56228753Smmpublic enum Option { 57228753Smm 58228753Smm SRC("-src", "Location of source files to be compiled") { 59313570Smm @Override 60228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 61228753Smm List<Path> paths = getFileListArg(iter, helper); 62228753Smm if (paths != null) 63228753Smm helper.sourceRoots(paths); 64228753Smm } 65228753Smm }, 66228753Smm SOURCEPATH("-sourcepath", "Specify search path for sources.") { 67228753Smm @Override 68228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 69228753Smm List<Path> paths = getFileListArg(iter, helper); 70228753Smm if (paths != null) 71228753Smm helper.sourcepath(paths); 72228753Smm } 73228753Smm }, 74313570Smm MODULEPATH("-modulepath", "Specify search path for modules.") { 75313570Smm @Override 76313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 77313570Smm List<Path> paths = getFileListArg(iter, helper); 78313570Smm if (paths != null) 79313570Smm helper.modulepath(paths); 80313570Smm } 81313570Smm }, 82313570Smm CLASSPATH("-classpath", "Specify search path for classes.") { 83313570Smm @Override 84313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 85313570Smm List<Path> paths = getFileListArg(iter, helper); 86313570Smm if (paths != null) 87313570Smm helper.classpath(paths); 88313570Smm } 89313570Smm }, 90313570Smm CP("-cp", "An alias for -classpath") { 91313570Smm @Override 92313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 93313570Smm CLASSPATH.processMatching(iter, helper); 94313570Smm } 95313570Smm }, 96313570Smm X("-x", "Exclude files matching the given pattern") { 97313570Smm @Override 98313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 99313570Smm String pattern = getFilePatternArg(iter, helper); 100313570Smm if (pattern != null) 101313570Smm helper.exclude(pattern); 102313570Smm } 103313570Smm }, 104313570Smm I("-i", "Include only files matching the given pattern") { 105313570Smm @Override 106313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 107228753Smm String pattern = getFilePatternArg(iter, helper); 108313570Smm if (pattern != null) 109313570Smm helper.include(pattern); 110313570Smm } 111313570Smm }, 112313570Smm TR("-tr", "Translate resources") { 113313570Smm @Override 114313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 115313570Smm 116313570Smm if (!iter.hasNext()) { 117313570Smm helper.reportError(arg + " must be followed by a translation rule"); 118313570Smm return; 119313570Smm } 120313570Smm 121313570Smm String trArg = iter.next(); 122313570Smm 123313570Smm // Validate argument syntax. Examples: 124313570Smm // .prop=com.sun.tools.javac.smart.CompileProperties 125313570Smm // .idl=com.sun.corba.CompileIdl 126313570Smm // .g3=antlr.CompileGrammar,debug=true 127313570Smm String ident = "[a-zA-Z_][a-zA-Z0-9_]*"; 128313570Smm Pattern p = Pattern.compile("(?<suffix>\\." + ident + ")=" + 129313570Smm "(?<class>" + ident + "(\\." + ident + ")*)" + 130313570Smm "(?<extra>,.*)?"); 131313570Smm // Check syntax 132313570Smm Matcher m = p.matcher(trArg); 133313570Smm if (!m.matches()) { 134313570Smm helper.reportError("The string \"" + trArg + "\" is not a " + 135313570Smm "valid translate pattern"); 136313570Smm return; 137313570Smm } 138313570Smm 139313570Smm // Extract relevant parts 140313570Smm String suffix = m.group("suffix"); 141313570Smm String classname = m.group("class"); 142313570Smm String extra = m.group("extra"); 143313570Smm 144313570Smm // Valid suffix? 145313570Smm if (suffix.matches("\\.(class|java)")) { 146313570Smm helper.reportError("You cannot have a translator for " + 147313570Smm suffix + " files!"); 148313570Smm return; 149313570Smm } 150313570Smm 151313570Smm // Construct transformer 152313570Smm try { 153313570Smm Class<?> trCls = Class.forName(classname); 154313570Smm Transformer transformer = 155313570Smm (Transformer) trCls.getConstructor().newInstance(); 156313570Smm transformer.setExtra(extra); 157313570Smm helper.addTransformer(suffix, transformer); 158313570Smm } catch (Exception e) { 159313570Smm helper.reportError("Cannot use " + classname + 160228753Smm " as a translator: " + e.getMessage()); 161313570Smm } 162313570Smm } 163313570Smm }, 164313570Smm COPY("-copy", "Copy resources") { 165313570Smm @Override 166313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 167313570Smm if (!iter.hasNext()) { 168313570Smm helper.reportError(arg + " must be followed by a resource type"); 169313570Smm return; 170313570Smm } 171313570Smm 172313570Smm String copyArg = iter.next(); 173313570Smm 174313570Smm // Validate argument syntax. Examples: .gif, .html 175313570Smm if (!copyArg.matches("\\.[a-zA-Z_][a-zA-Z0-9_]*")) { 176313570Smm helper.reportError("The string \"" + copyArg + "\" is not a " + 177313570Smm "valid resource type."); 178313570Smm return; 179313570Smm } 180313570Smm 181313570Smm helper.addTransformer(copyArg, new CopyFile()); 182313570Smm } 183313570Smm }, 184313570Smm J("-j", "Number of cores") { 185313570Smm @Override 186313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 187313570Smm if (!iter.hasNext() || !iter.peek().matches("\\d+")) { 188313570Smm helper.reportError(arg + " must be followed by an integer"); 189313570Smm return; 190313570Smm } 191313570Smm helper.numCores(Integer.parseInt(iter.next())); 192313570Smm } 193313570Smm }, 194313570Smm SERVER("--server:", "Specify server configuration file of running server") { 195313570Smm @Override 196313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 197313570Smm helper.serverConf(iter.current().substring(arg.length())); 198313570Smm } 199313570Smm }, 200313570Smm STARTSERVER("--startserver:", "Start server and use the given configuration file") { 201313570Smm @Override 202313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 203313570Smm helper.startServerConf(iter.current().substring(arg.length())); 204313570Smm } 205313570Smm }, 206313570Smm IMPLICIT("-implicit:", "Specify how to treat implicitly referenced source code") { 207313570Smm @Override 208313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 209313570Smm helper.implicit(iter.current().substring(arg.length())); 210313570Smm } 211313570Smm }, 212313570Smm LOG("--log=", "Specify logging level") { 213313570Smm @Override 214313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 215228753Smm helper.logLevel(iter.current().substring(arg.length())); 216313570Smm } 217228753Smm }, 218228753Smm VERBOSE("-verbose", "Set verbosity level to \"info\"") { 219228753Smm @Override 220228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 221228753Smm helper.logLevel("info"); 222232153Smm } 223232153Smm }, 224228753Smm PERMIT_ARTIFACT("--permit-artifact=", "Allow this artifact in destination directory") { 225228753Smm @Override 226228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 227228753Smm String a = iter.current().substring(arg.length()); 228248616Smm helper.permitArtifact(Paths.get(a).toFile().getAbsolutePath()); 229228753Smm } 230228753Smm }, 231228753Smm PERMIT_UNIDENTIFIED_ARTIFACTS("--permit-unidentified-artifacts", "Allow unidentified artifacts in destination directory") { 232228753Smm @Override 233228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 234228753Smm helper.permitUnidentifiedArtifacts(); 235228753Smm } 236228753Smm }, 237228753Smm PERMIT_SOURCES_WITHOUT_PACKAGE("--permit-sources-without-package", "Permit sources in the default package") { 238228753Smm @Override 239228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 240228753Smm helper.permitDefaultPackage(); 241313570Smm } 242228753Smm }, 243228753Smm COMPARE_FOUND_SOURCES("--compare-found-sources", "Compare found sources with given sources") { 244228753Smm @Override 245313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 246228753Smm Path referenceSourceList = getFileArg(iter, helper, true, false); 247228753Smm if (referenceSourceList != null) 248228753Smm helper.compareFoundSources(referenceSourceList); 249228753Smm } 250313570Smm }, 251228753Smm D("-d", "Output destination directory") { 252228753Smm @Override 253228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 254228753Smm Path dir = getFileArg(iter, helper, false, true); 255228753Smm if (dir != null) 256228753Smm helper.destDir(dir); 257313570Smm } 258228753Smm }, 259228753Smm S("-s", "Directory for generated sources") { 260228753Smm @Override 261228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 262232153Smm Path dir = getFileArg(iter, helper, false, true); 263232153Smm if (dir != null) 264228753Smm helper.generatedSourcesDir(dir); 265228753Smm } 266228753Smm }, 267228753Smm H("-h", "Directory for header files") { 268228753Smm @Override 269228753Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 270228753Smm Path dir = getFileArg(iter, helper, false, true); 271313570Smm if (dir != null) 272313570Smm helper.headerDir(dir); 273228753Smm } 274228753Smm }, 275313570Smm STATE_DIR("--state-dir=", "Directory used to store sjavac state and log files.") { 276232153Smm @Override 277313570Smm protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 278232153Smm String p = iter.current().substring(arg.length()); 279232153Smm helper.stateDir(Paths.get(p)); 280228753Smm } 281228753Smm }; 282228753Smm 283228753Smm 284232153Smm public final String arg; 285228753Smm 286228753Smm final String description; 287228753Smm 288228753Smm private Option(String arg, String description) { 289228753Smm this.arg = arg; 290228753Smm this.description = description; 291228753Smm } 292228753Smm 293228753Smm /** Retrieve and verify syntax of file list argument. */ 294228753Smm List<Path> getFileListArg(ArgumentIterator iter, OptionHelper helper) { 295228753Smm if (!iter.hasNext()) { 296228753Smm helper.reportError(arg + " must be followed by a list of files " + 297228753Smm "separated by " + File.pathSeparator); 298228753Smm return null; 299313570Smm } 300313570Smm List<Path> result = new ArrayList<>(); 301228753Smm for (String pathStr : iter.next().split(File.pathSeparator)) 302228753Smm result.add(Paths.get(pathStr)); 303228753Smm return result; 304228753Smm } 305228753Smm 306228753Smm /** Retrieve and verify syntax of file argument. */ 307313570Smm Path getFileArg(ArgumentIterator iter, OptionHelper helper, boolean fileAcceptable, boolean dirAcceptable) { 308313570Smm 309313570Smm if (!iter.hasNext()) { 310313570Smm String errmsg = arg + " must be followed by "; 311228753Smm if (fileAcceptable && dirAcceptable) errmsg += "a file or directory."; 312228753Smm else if (fileAcceptable) errmsg += "a file."; 313228753Smm else if (dirAcceptable) errmsg += "a directory."; 314228753Smm else throw new IllegalArgumentException("File or directory must be acceptable."); 315228753Smm helper.reportError(errmsg); 316228753Smm return null; 317228753Smm } 318228753Smm 319228753Smm return Paths.get(iter.next()); 320228753Smm } 321228753Smm 322228753Smm /** Retrieve the next file or package argument. */ 323228753Smm String getFilePatternArg(ArgumentIterator iter, OptionHelper helper) { 324232153Smm 325232153Smm if (!iter.hasNext()) { 326228753Smm helper.reportError(arg + " must be followed by a glob pattern."); 327313570Smm return null; 328313570Smm } 329313570Smm 330313570Smm return iter.next(); 331313570Smm } 332313570Smm 333313570Smm // Future cleanup: Change the "=" syntax to ":" syntax to be consistent and 334313570Smm // to follow the javac-option style. 335313570Smm 336313570Smm public boolean hasOption() { 337313570Smm return arg.endsWith(":") || arg.endsWith("="); 338313570Smm } 339313570Smm 340313570Smm 341313570Smm /** 342313570Smm * Process current argument of argIter. 343313570Smm * 344313570Smm * It's final, since the option customization is typically done in 345313570Smm * processMatching. 346313570Smm * 347313570Smm * @param argIter Iterator to read current and succeeding arguments from. 348313570Smm * @param helper The helper to report back to. 349313570Smm * @return true iff the argument was processed by this option. 350313570Smm */ 351313570Smm public final boolean processCurrent(ArgumentIterator argIter, 352313570Smm OptionHelper helper) { 353313570Smm String fullArg = argIter.current(); // "-tr" or "-log=level" 354313570Smm if (hasOption() ? fullArg.startsWith(arg) : fullArg.equals(arg)) { 355313570Smm processMatching(argIter, helper); 356313570Smm return true; 357313570Smm } 358313570Smm // Did not match 359313570Smm return false; 360313570Smm } 361313570Smm 362313570Smm /** Called by process if the current argument matches this option. */ 363313570Smm protected abstract void processMatching(ArgumentIterator argIter, 364313570Smm OptionHelper helper); 365313570Smm} 366313570Smm