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