Option.java revision 3195:88a874f33d6d
1/* 2 * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.tools.sjavac.options; 27 28import java.io.File; 29import java.nio.file.Path; 30import java.nio.file.Paths; 31import java.util.ArrayList; 32import java.util.List; 33import java.util.regex.Matcher; 34import java.util.regex.Pattern; 35 36import com.sun.tools.sjavac.CopyFile; 37import com.sun.tools.sjavac.Transformer; 38 39 40/** 41 * Sjavac options can be classified as: 42 * 43 * (1) relevant only for sjavac, such as --server 44 * (2) relevant for sjavac and javac, such as -d, or 45 * (3) relevant only for javac, such as -g. 46 * 47 * This enum represents all options from (1) and (2). Note that instances of 48 * this enum only entail static information about the option. For storage of 49 * option values, refer to com.sun.tools.sjavac.options.Options. 50 * 51 * <p><b>This is NOT part of any supported API. 52 * If you write code that depends on this, you do so at your own risk. 53 * This code and its internal interfaces are subject to change or 54 * deletion without notice.</b> 55 */ 56public enum Option { 57 58 SRC("-src", "Location of source files to be compiled") { 59 @Override 60 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 61 List<Path> paths = getFileListArg(iter, helper); 62 if (paths != null) 63 helper.sourceRoots(paths); 64 } 65 }, 66 SOURCEPATH("-sourcepath", "Specify search path for sources.") { 67 @Override 68 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 69 List<Path> paths = getFileListArg(iter, helper); 70 if (paths != null) 71 helper.sourcepath(paths); 72 } 73 }, 74 MODULEPATH("-modulepath", "Specify search path for modules.") { 75 @Override 76 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 77 List<Path> paths = getFileListArg(iter, helper); 78 if (paths != null) 79 helper.modulepath(paths); 80 } 81 }, 82 CLASSPATH("-classpath", "Specify search path for classes.") { 83 @Override 84 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 85 List<Path> paths = getFileListArg(iter, helper); 86 if (paths != null) 87 helper.classpath(paths); 88 } 89 }, 90 CP("-cp", "An alias for -classpath") { 91 @Override 92 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 93 CLASSPATH.processMatching(iter, helper); 94 } 95 }, 96 X("-x", "Exclude files matching the given pattern") { 97 @Override 98 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 99 String pattern = getFilePatternArg(iter, helper); 100 if (pattern != null) 101 helper.exclude(pattern); 102 } 103 }, 104 I("-i", "Include only files matching the given pattern") { 105 @Override 106 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 107 String pattern = getFilePatternArg(iter, helper); 108 if (pattern != null) 109 helper.include(pattern); 110 } 111 }, 112 TR("-tr", "Translate resources") { 113 @Override 114 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 115 116 if (!iter.hasNext()) { 117 helper.reportError(arg + " must be followed by a translation rule"); 118 return; 119 } 120 121 String trArg = iter.next(); 122 123 // Validate argument syntax. Examples: 124 // .prop=com.sun.tools.javac.smart.CompileProperties 125 // .idl=com.sun.corba.CompileIdl 126 // .g3=antlr.CompileGrammar,debug=true 127 String ident = "[a-zA-Z_][a-zA-Z0-9_]*"; 128 Pattern p = Pattern.compile("(?<suffix>\\." + ident + ")=" + 129 "(?<class>" + ident + "(\\." + ident + ")*)" + 130 "(?<extra>,.*)?"); 131 // Check syntax 132 Matcher m = p.matcher(trArg); 133 if (!m.matches()) { 134 helper.reportError("The string \"" + trArg + "\" is not a " + 135 "valid translate pattern"); 136 return; 137 } 138 139 // Extract relevant parts 140 String suffix = m.group("suffix"); 141 String classname = m.group("class"); 142 String extra = m.group("extra"); 143 144 // Valid suffix? 145 if (suffix.matches("\\.(class|java)")) { 146 helper.reportError("You cannot have a translator for " + 147 suffix + " files!"); 148 return; 149 } 150 151 // Construct transformer 152 try { 153 Class<?> trCls = Class.forName(classname); 154 Transformer transformer = (Transformer) trCls.newInstance(); 155 transformer.setExtra(extra); 156 helper.addTransformer(suffix, transformer); 157 } catch (Exception e) { 158 helper.reportError("Cannot use " + classname + 159 " as a translator: " + e.getMessage()); 160 } 161 } 162 }, 163 COPY("-copy", "Copy resources") { 164 @Override 165 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 166 if (!iter.hasNext()) { 167 helper.reportError(arg + " must be followed by a resource type"); 168 return; 169 } 170 171 String copyArg = iter.next(); 172 173 // Validate argument syntax. Examples: .gif, .html 174 if (!copyArg.matches("\\.[a-zA-Z_][a-zA-Z0-9_]*")) { 175 helper.reportError("The string \"" + copyArg + "\" is not a " + 176 "valid resource type."); 177 return; 178 } 179 180 helper.addTransformer(copyArg, new CopyFile()); 181 } 182 }, 183 J("-j", "Number of cores") { 184 @Override 185 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 186 if (!iter.hasNext() || !iter.peek().matches("\\d+")) { 187 helper.reportError(arg + " must be followed by an integer"); 188 return; 189 } 190 helper.numCores(Integer.parseInt(iter.next())); 191 } 192 }, 193 SERVER("--server:", "Specify server configuration file of running server") { 194 @Override 195 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 196 helper.serverConf(iter.current().substring(arg.length())); 197 } 198 }, 199 STARTSERVER("--startserver:", "Start server and use the given configuration file") { 200 @Override 201 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 202 helper.startServerConf(iter.current().substring(arg.length())); 203 } 204 }, 205 IMPLICIT("-implicit:", "Specify how to treat implicitly referenced source code") { 206 @Override 207 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 208 helper.implicit(iter.current().substring(arg.length())); 209 } 210 }, 211 LOG("--log=", "Specify logging level") { 212 @Override 213 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 214 helper.logLevel(iter.current().substring(arg.length())); 215 } 216 }, 217 VERBOSE("-verbose", "Set verbosity level to \"info\"") { 218 @Override 219 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 220 helper.logLevel("info"); 221 } 222 }, 223 PERMIT_ARTIFACT("--permit-artifact=", "Allow this artifact in destination directory") { 224 @Override 225 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 226 String a = iter.current().substring(arg.length()); 227 helper.permitArtifact(Paths.get(a).toFile().getAbsolutePath()); 228 } 229 }, 230 PERMIT_UNIDENTIFIED_ARTIFACTS("--permit-unidentified-artifacts", "Allow unidentified artifacts in destination directory") { 231 @Override 232 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 233 helper.permitUnidentifiedArtifacts(); 234 } 235 }, 236 PERMIT_SOURCES_WITHOUT_PACKAGE("--permit-sources-without-package", "Permit sources in the default package") { 237 @Override 238 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 239 helper.permitDefaultPackage(); 240 } 241 }, 242 COMPARE_FOUND_SOURCES("--compare-found-sources", "Compare found sources with given sources") { 243 @Override 244 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 245 Path referenceSourceList = getFileArg(iter, helper, true, false); 246 if (referenceSourceList != null) 247 helper.compareFoundSources(referenceSourceList); 248 } 249 }, 250 D("-d", "Output destination directory") { 251 @Override 252 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 253 Path dir = getFileArg(iter, helper, false, true); 254 if (dir != null) 255 helper.destDir(dir); 256 } 257 }, 258 S("-s", "Directory for generated sources") { 259 @Override 260 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 261 Path dir = getFileArg(iter, helper, false, true); 262 if (dir != null) 263 helper.generatedSourcesDir(dir); 264 } 265 }, 266 H("-h", "Directory for header files") { 267 @Override 268 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 269 Path dir = getFileArg(iter, helper, false, true); 270 if (dir != null) 271 helper.headerDir(dir); 272 } 273 }, 274 STATE_DIR("--state-dir=", "Directory used to store sjavac state and log files.") { 275 @Override 276 protected void processMatching(ArgumentIterator iter, OptionHelper helper) { 277 String p = iter.current().substring(arg.length()); 278 helper.stateDir(Paths.get(p)); 279 } 280 }; 281 282 283 public final String arg; 284 285 final String description; 286 287 private Option(String arg, String description) { 288 this.arg = arg; 289 this.description = description; 290 } 291 292 /** Retrieve and verify syntax of file list argument. */ 293 List<Path> getFileListArg(ArgumentIterator iter, OptionHelper helper) { 294 if (!iter.hasNext()) { 295 helper.reportError(arg + " must be followed by a list of files " + 296 "separated by " + File.pathSeparator); 297 return null; 298 } 299 List<Path> result = new ArrayList<>(); 300 for (String pathStr : iter.next().split(File.pathSeparator)) 301 result.add(Paths.get(pathStr)); 302 return result; 303 } 304 305 /** Retrieve and verify syntax of file argument. */ 306 Path getFileArg(ArgumentIterator iter, OptionHelper helper, boolean fileAcceptable, boolean dirAcceptable) { 307 308 if (!iter.hasNext()) { 309 String errmsg = arg + " must be followed by "; 310 if (fileAcceptable && dirAcceptable) errmsg += "a file or directory."; 311 else if (fileAcceptable) errmsg += "a file."; 312 else if (dirAcceptable) errmsg += "a directory."; 313 else throw new IllegalArgumentException("File or directory must be acceptable."); 314 helper.reportError(errmsg); 315 return null; 316 } 317 318 return Paths.get(iter.next()); 319 } 320 321 /** Retrieve the next file or package argument. */ 322 String getFilePatternArg(ArgumentIterator iter, OptionHelper helper) { 323 324 if (!iter.hasNext()) { 325 helper.reportError(arg + " must be followed by a glob pattern."); 326 return null; 327 } 328 329 return iter.next(); 330 } 331 332 // Future cleanup: Change the "=" syntax to ":" syntax to be consistent and 333 // to follow the javac-option style. 334 335 public boolean hasOption() { 336 return arg.endsWith(":") || arg.endsWith("="); 337 } 338 339 340 /** 341 * Process current argument of argIter. 342 * 343 * It's final, since the option customization is typically done in 344 * processMatching. 345 * 346 * @param argIter Iterator to read current and succeeding arguments from. 347 * @param helper The helper to report back to. 348 * @return true iff the argument was processed by this option. 349 */ 350 public final boolean processCurrent(ArgumentIterator argIter, 351 OptionHelper helper) { 352 String fullArg = argIter.current(); // "-tr" or "-log=level" 353 if (hasOption() ? fullArg.startsWith(arg) : fullArg.equals(arg)) { 354 processMatching(argIter, helper); 355 return true; 356 } 357 // Did not match 358 return false; 359 } 360 361 /** Called by process if the current argument matches this option. */ 362 protected abstract void processMatching(ArgumentIterator argIter, 363 OptionHelper helper); 364} 365