1 /* 2 * Copyright (c) 1997, 2013, 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 26 package com.sun.tools.internal.ws.wscompile; 27 28 import com.sun.tools.internal.ws.resources.WscompileMessages; 29 import com.sun.tools.internal.ws.Invoker; 30 31 import javax.annotation.processing.Filer; 32 import java.io.File; 33 import java.io.IOException; 34 import java.net.MalformedURLException; 35 import java.net.URL; 36 import java.net.URLClassLoader; 37 import java.nio.charset.Charset; 38 import java.nio.charset.IllegalCharsetNameException; 39 import java.text.MessageFormat; 40 import java.util.ArrayList; 41 import java.util.List; 42 import java.util.StringTokenizer; 43 44 /** 45 * Provide common jaxws tool options. 46 * 47 * @author Vivek Pandey 48 */ 49 public class Options { 50 /** 51 * -verbose 52 */ 53 public boolean verbose; 54 55 /** 56 * - quite 57 */ 58 public boolean quiet; 59 60 /** 61 * -keep 62 */ 63 public boolean keep; 64 65 66 67 /** 68 * -d 69 */ 70 public File destDir = new File("."); 71 72 73 /** 74 * -s 75 */ 76 public File sourceDir; 77 78 /** 79 * The filer that can use used to write out the generated files 80 */ 81 public Filer filer; 82 83 /** 84 * -encoding 85 */ 86 public String encoding; 87 88 public String classpath = System.getProperty("java.class.path"); 89 90 91 /** 92 * -Xnocompile 93 */ 94 public boolean nocompile; 95 96 /** 97 * Disable secure xml processing. 98 * -XdisableSecureXmlProcessing 99 */ 100 public boolean disableSecureXmlProcessing = false; 101 102 public enum Target { 103 V2_0, V2_1, V2_2; 104 105 /** 106 * Returns true if this version is equal or later than the given one. 107 */ 108 public boolean isLaterThan(Target t) { 109 return this.ordinal() >= t.ordinal(); 110 } 111 112 /** 113 * Parses "2.0" and "2.1" into the {@link Target} object. 114 * 115 * @return null for parsing failure. 116 */ 117 public static Target parse(String token) { 118 if (token.equals("2.0")) 119 return Target.V2_0; 120 else if (token.equals("2.1")) 121 return Target.V2_1; 122 else if (token.equals("2.2")) 123 return Target.V2_2; 124 return null; 125 } 126 127 /** 128 * Gives the String representation of the {@link Target} 129 */ 130 public String getVersion(){ 131 switch(this){ 132 case V2_0: 133 return "2.0"; 134 case V2_1: 135 return "2.1"; 136 case V2_2: 137 return "2.2"; 138 default: 139 return null; 140 } 141 } 142 143 public static Target getDefault() { 144 return V2_2; 145 } 146 147 public static Target getLoadedAPIVersion() { 148 return LOADED_API_VERSION; 149 } 150 151 private static final Target LOADED_API_VERSION; 152 153 static { 154 // check if we are indeed loading JAX-WS 2.2 API 155 if (Invoker.checkIfLoading22API()) { 156 LOADED_API_VERSION = Target.V2_2; 157 } // check if we are indeed loading JAX-WS 2.1 API 158 else if (Invoker.checkIfLoading21API()) { 159 LOADED_API_VERSION = Target.V2_1; 160 } else { 161 LOADED_API_VERSION = Target.V2_0; 162 } 163 } 164 } 165 166 public Target target = Target.V2_2; 167 168 /** 169 * strictly follow the compatibility rules specified in JAXWS spec 170 */ 171 public static final int STRICT = 1; 172 173 /** 174 * loosely follow the compatibility rules and allow the use of vendor 175 * binding extensions 176 */ 177 public static final int EXTENSION = 2; 178 179 /** 180 * this switch determines how carefully the compiler will follow 181 * the compatibility rules in the spec. Either <code>STRICT</code> 182 * or <code>EXTENSION</code>. 183 */ 184 public int compatibilityMode = STRICT; 185 186 public boolean isExtensionMode() { 187 return compatibilityMode == EXTENSION; 188 } 189 190 public boolean debug = false; 191 192 /** 193 * -Xdebug - gives complete stack trace 194 */ 195 public boolean debugMode = false; 196 197 198 private final List<File> generatedFiles = new ArrayList<File>(); 199 private ClassLoader classLoader; 200 201 202 /** 203 * Remember info on generated source file generated so that it 204 * can be removed later, if appropriate. 205 */ 206 public void addGeneratedFile(File file) { 207 generatedFiles.add(file); 208 } 209 210 /** 211 * Remove generated files 212 */ 213 public void removeGeneratedFiles(){ 214 for(File file : generatedFiles){ 215 if (file.getName().endsWith(".java")) { 216 boolean deleted = file.delete(); 217 if (verbose && !deleted) { 218 System.out.println(MessageFormat.format("{0} could not be deleted.", file)); 219 } 220 } 221 } 222 generatedFiles.clear(); 223 } 224 225 /** 226 * Return all the generated files and its types. 227 */ 228 public Iterable<File> getGeneratedFiles() { 229 return generatedFiles; 230 } 231 232 /** 233 * Delete all the generated source files made during the execution 234 * of this environment (those that have been registered with the 235 * "addGeneratedFile" method). 236 */ 237 public void deleteGeneratedFiles() { 238 synchronized (generatedFiles) { 239 for (File file : generatedFiles) { 240 if (file.getName().endsWith(".java")) { 241 boolean deleted = file.delete(); 242 if (verbose && !deleted) { 243 System.out.println(MessageFormat.format("{0} could not be deleted.", file)); 244 } 245 } 246 } 247 generatedFiles.clear(); 248 } 249 } 250 251 /** 252 * Parses arguments and fill fields of this object. 253 * 254 * @exception BadCommandLineException 255 * thrown when there's a problem in the command-line arguments 256 */ 257 public void parseArguments( String[] args ) throws BadCommandLineException { 258 259 for (int i = 0; i < args.length; i++) { 260 if(args[i].length()==0) 261 throw new BadCommandLineException(); 262 if (args[i].charAt(0) == '-') { 263 int j = parseArguments(args,i); 264 if(j==0) 265 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_INVALID_OPTION(args[i])); 266 i += (j-1); 267 } else { 268 addFile(args[i]); 269 } 270 } 271 if(destDir == null) 272 destDir = new File("."); 273 if(sourceDir == null) 274 sourceDir = destDir; 275 } 276 277 278 /** 279 * Adds a file from the argume 280 * 281 * @param arg a file, could be a wsdl or xsd or a Class 282 */ 283 protected void addFile(String arg) throws BadCommandLineException {} 284 285 /** 286 * Parses an option <code>args[i]</code> and return 287 * the number of tokens consumed. 288 * 289 * @return 290 * 0 if the argument is not understood. Returning 0 291 * will let the caller report an error. 292 * @exception BadCommandLineException 293 * If the callee wants to provide a custom message for an error. 294 */ 295 protected int parseArguments(String[] args, int i) throws BadCommandLineException { 296 if (args[i].equals("-g")) { 297 debug = true; 298 return 1; 299 } else if (args[i].equals("-Xdebug")) { 300 debugMode = true; 301 return 1; 302 } else if (args[i].equals("-Xendorsed")) { 303 // this option is processed much earlier, so just ignore. 304 return 1; 305 } else if (args[i].equals("-verbose")) { 306 verbose = true; 307 return 1; 308 } else if (args[i].equals("-quiet")) { 309 quiet = true; 310 return 1; 311 } else if (args[i].equals("-keep")) { 312 keep = true; 313 return 1; 314 } else if (args[i].equals("-target")) { 315 String token = requireArgument("-target", args, ++i); 316 target = Target.parse(token); 317 if(target == null) 318 throw new BadCommandLineException(WscompileMessages.WSIMPORT_ILLEGAL_TARGET_VERSION(token)); 319 return 2; 320 } else if (args[i].equals("-classpath") || args[i].equals("-cp")) { 321 classpath = requireArgument("-classpath", args, ++i) + File.pathSeparator + System.getProperty("java.class.path"); 322 return 2; 323 } else if (args[i].equals("-d")) { 324 destDir = new File(requireArgument("-d", args, ++i)); 325 if (!destDir.exists()) 326 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_NO_SUCH_DIRECTORY(destDir.getPath())); 327 return 2; 328 } else if (args[i].equals("-s")) { 329 sourceDir = new File(requireArgument("-s", args, ++i)); 330 keep = true; 331 if (!sourceDir.exists()) { 332 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_NO_SUCH_DIRECTORY(sourceDir.getPath())); 333 } 334 return 2; 335 } else if (args[i].equals("-extension")) { 336 compatibilityMode = EXTENSION; 337 return 1; 338 } else if (args[i].startsWith("-help")) { 339 WeAreDone done = new WeAreDone(); 340 done.initOptions(this); 341 throw done; 342 } else if (args[i].equals("-Xnocompile")) { 343 // -nocompile implies -keep. this is undocumented switch. 344 nocompile = true; 345 keep = true; 346 return 1; 347 } else if (args[i].equals("-encoding")) { 348 encoding = requireArgument("-encoding", args, ++i); 349 try { 350 if (!Charset.isSupported(encoding)) { 351 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_UNSUPPORTED_ENCODING(encoding)); 352 } 353 } catch (IllegalCharsetNameException icne) { 354 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_UNSUPPORTED_ENCODING(encoding)); 355 } 356 return 2; 357 } else if (args[i].equals("-XdisableSecureXmlProcessing")) { 358 disableSecureXmlProcessing= true; 359 return 1; 360 } 361 return 0; 362 } 363 364 /** 365 * Obtains an operand and reports an error if it's not there. 366 */ 367 public String requireArgument(String optionName, String[] args, int i) throws BadCommandLineException { 368 //if (i == args.length || args[i].startsWith("-")) { 369 if (args[i].startsWith("-")) { 370 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_MISSING_OPTION_ARGUMENT(optionName)); 371 } 372 return args[i]; 373 } 374 375 376 377 /** 378 * Used to signal that we've finished processing. 379 */ 380 public static final class WeAreDone extends BadCommandLineException {} 381 382 /** 383 * Get a URLClassLoader from using the classpath 384 */ 385 public ClassLoader getClassLoader() { 386 if (classLoader == null) { 387 classLoader = 388 new URLClassLoader(pathToURLs(classpath), 389 this.getClass().getClassLoader()); 390 } 391 return classLoader; 392 } 393 394 /** 395 * Utility method for converting a search path string to an array 396 * of directory and JAR file URLs. 397 * 398 * @param path the search path string 399 * @return the resulting array of directory and JAR file URLs 400 */ 401 public static URL[] pathToURLs(String path) { 402 StringTokenizer st = new StringTokenizer(path, File.pathSeparator); 403 URL[] urls = new URL[st.countTokens()]; 404 int count = 0; 405 while (st.hasMoreTokens()) { 406 URL url = fileToURL(new File(st.nextToken())); 407 if (url != null) { 408 urls[count++] = url; 409 } 410 } 411 if (urls.length != count) { 412 URL[] tmp = new URL[count]; 413 System.arraycopy(urls, 0, tmp, 0, count); 414 urls = tmp; 415 } 416 return urls; 417 } 418 419 /** 420 * Returns the directory or JAR file URL corresponding to the specified 421 * local file name. 422 * 423 * @param file the File object 424 * @return the resulting directory or JAR file URL, or null if unknown 425 */ 426 public static URL fileToURL(File file) { 427 String name; 428 try { 429 name = file.getCanonicalPath(); 430 } catch (IOException e) { 431 name = file.getAbsolutePath(); 432 } 433 name = name.replace(File.separatorChar, '/'); 434 if (!name.startsWith("/")) { 435 name = "/" + name; 436 } 437 438 // If the file does not exist, then assume that it's a directory 439 if (!file.isFile()) { 440 name = name + "/"; 441 } 442 try { 443 return new URL("file", "", name); 444 } catch (MalformedURLException e) { 445 throw new IllegalArgumentException("file"); 446 } 447 } 448 449 }