ohair@286: /* alanb@368: * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. ohair@286: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. ohair@286: * ohair@286: * This code is free software; you can redistribute it and/or modify it ohair@286: * under the terms of the GNU General Public License version 2 only, as ohair@286: * published by the Free Software Foundation. Oracle designates this ohair@286: * particular file as subject to the "Classpath" exception as provided ohair@286: * by Oracle in the LICENSE file that accompanied this code. ohair@286: * ohair@286: * This code is distributed in the hope that it will be useful, but WITHOUT ohair@286: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or ohair@286: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License ohair@286: * version 2 for more details (a copy is included in the LICENSE file that ohair@286: * accompanied this code). ohair@286: * ohair@286: * You should have received a copy of the GNU General Public License version ohair@286: * 2 along with this work; if not, write to the Free Software Foundation, ohair@286: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. ohair@286: * ohair@286: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA ohair@286: * or visit www.oracle.com if you need additional information or have any ohair@286: * questions. ohair@286: */ ohair@286: ohair@286: package com.sun.tools.internal.ws.wscompile; ohair@286: ohair@286: import com.sun.tools.internal.ws.resources.WscompileMessages; ohair@286: import com.sun.tools.internal.ws.Invoker; ohair@286: ohair@286: import javax.annotation.processing.Filer; ohair@286: import java.io.File; ohair@286: import java.io.IOException; ohair@286: import java.net.MalformedURLException; ohair@286: import java.net.URL; ohair@286: import java.net.URLClassLoader; ohair@286: import java.nio.charset.Charset; ohair@286: import java.nio.charset.IllegalCharsetNameException; alanb@368: import java.text.MessageFormat; ohair@286: import java.util.ArrayList; ohair@286: import java.util.List; ohair@286: import java.util.StringTokenizer; ohair@286: ohair@286: /** ohair@286: * Provide common jaxws tool options. ohair@286: * ohair@286: * @author Vivek Pandey ohair@286: */ ohair@286: public class Options { ohair@286: /** ohair@286: * -verbose ohair@286: */ ohair@286: public boolean verbose; ohair@286: ohair@286: /** ohair@286: * - quite ohair@286: */ ohair@286: public boolean quiet; ohair@286: ohair@286: /** ohair@286: * -keep ohair@286: */ ohair@286: public boolean keep; ohair@286: ohair@286: ohair@286: ohair@286: /** ohair@286: * -d ohair@286: */ ohair@286: public File destDir = new File("."); ohair@286: ohair@286: ohair@286: /** ohair@286: * -s ohair@286: */ ohair@286: public File sourceDir; ohair@286: ohair@286: /** ohair@286: * The filer that can use used to write out the generated files ohair@286: */ ohair@286: public Filer filer; ohair@286: ohair@286: /** ohair@286: * -encoding ohair@286: */ ohair@286: public String encoding; ohair@286: ohair@286: public String classpath = System.getProperty("java.class.path"); ohair@286: mkos@408: /** mkos@408: * -javacOptions mkos@408: * mkos@408: * @since 2.2.9 mkos@408: */ mkos@408: public List javacOptions; mkos@408: ohair@286: ohair@286: /** ohair@286: * -Xnocompile ohair@286: */ ohair@286: public boolean nocompile; ohair@286: alanb@368: /** mkos@408: * If true XML security features when parsing XML documents will be disabled. mkos@408: * The default value is false. mkos@408: * mkos@408: * Boolean mkos@408: * @since 2.2.9 alanb@368: */ mkos@408: public boolean disableXmlSecurity; alanb@368: ohair@286: public enum Target { ohair@286: V2_0, V2_1, V2_2; ohair@286: ohair@286: /** ohair@286: * Returns true if this version is equal or later than the given one. ohair@286: */ ohair@286: public boolean isLaterThan(Target t) { ohair@286: return this.ordinal() >= t.ordinal(); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Parses "2.0" and "2.1" into the {@link Target} object. ohair@286: * ohair@286: * @return null for parsing failure. ohair@286: */ ohair@286: public static Target parse(String token) { ohair@286: if (token.equals("2.0")) ohair@286: return Target.V2_0; ohair@286: else if (token.equals("2.1")) ohair@286: return Target.V2_1; ohair@286: else if (token.equals("2.2")) ohair@286: return Target.V2_2; ohair@286: return null; ohair@286: } ohair@286: ohair@286: /** ohair@286: * Gives the String representation of the {@link Target} ohair@286: */ ohair@286: public String getVersion(){ ohair@286: switch(this){ ohair@286: case V2_0: ohair@286: return "2.0"; ohair@286: case V2_1: ohair@286: return "2.1"; ohair@286: case V2_2: ohair@286: return "2.2"; ohair@286: default: ohair@286: return null; ohair@286: } ohair@286: } ohair@286: ohair@286: public static Target getDefault() { ohair@286: return V2_2; ohair@286: } ohair@286: ohair@286: public static Target getLoadedAPIVersion() { ohair@286: return LOADED_API_VERSION; ohair@286: } ohair@286: ohair@286: private static final Target LOADED_API_VERSION; ohair@286: ohair@286: static { ohair@286: // check if we are indeed loading JAX-WS 2.2 API ohair@286: if (Invoker.checkIfLoading22API()) { ohair@286: LOADED_API_VERSION = Target.V2_2; ohair@286: } // check if we are indeed loading JAX-WS 2.1 API ohair@286: else if (Invoker.checkIfLoading21API()) { ohair@286: LOADED_API_VERSION = Target.V2_1; ohair@286: } else { ohair@286: LOADED_API_VERSION = Target.V2_0; ohair@286: } ohair@286: } ohair@286: } ohair@286: ohair@286: public Target target = Target.V2_2; ohair@286: ohair@286: /** ohair@286: * strictly follow the compatibility rules specified in JAXWS spec ohair@286: */ ohair@286: public static final int STRICT = 1; ohair@286: ohair@286: /** ohair@286: * loosely follow the compatibility rules and allow the use of vendor ohair@286: * binding extensions ohair@286: */ ohair@286: public static final int EXTENSION = 2; ohair@286: ohair@286: /** ohair@286: * this switch determines how carefully the compiler will follow ohair@286: * the compatibility rules in the spec. Either STRICT ohair@286: * or EXTENSION. ohair@286: */ ohair@286: public int compatibilityMode = STRICT; ohair@286: ohair@286: public boolean isExtensionMode() { ohair@286: return compatibilityMode == EXTENSION; ohair@286: } ohair@286: ohair@286: public boolean debug = false; ohair@286: ohair@286: /** ohair@286: * -Xdebug - gives complete stack trace ohair@286: */ ohair@286: public boolean debugMode = false; ohair@286: ohair@286: ohair@286: private final List generatedFiles = new ArrayList(); ohair@286: private ClassLoader classLoader; ohair@286: ohair@286: ohair@286: /** ohair@286: * Remember info on generated source file generated so that it ohair@286: * can be removed later, if appropriate. ohair@286: */ ohair@286: public void addGeneratedFile(File file) { ohair@286: generatedFiles.add(file); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Remove generated files ohair@286: */ ohair@286: public void removeGeneratedFiles(){ ohair@286: for(File file : generatedFiles){ ohair@286: if (file.getName().endsWith(".java")) { alanb@368: boolean deleted = file.delete(); alanb@368: if (verbose && !deleted) { alanb@368: System.out.println(MessageFormat.format("{0} could not be deleted.", file)); alanb@368: } ohair@286: } ohair@286: } ohair@286: generatedFiles.clear(); ohair@286: } ohair@286: ohair@286: /** ohair@286: * Return all the generated files and its types. ohair@286: */ ohair@286: public Iterable getGeneratedFiles() { ohair@286: return generatedFiles; ohair@286: } ohair@286: ohair@286: /** ohair@286: * Delete all the generated source files made during the execution ohair@286: * of this environment (those that have been registered with the ohair@286: * "addGeneratedFile" method). ohair@286: */ ohair@286: public void deleteGeneratedFiles() { ohair@286: synchronized (generatedFiles) { ohair@286: for (File file : generatedFiles) { ohair@286: if (file.getName().endsWith(".java")) { alanb@368: boolean deleted = file.delete(); alanb@368: if (verbose && !deleted) { alanb@368: System.out.println(MessageFormat.format("{0} could not be deleted.", file)); alanb@368: } ohair@286: } ohair@286: } ohair@286: generatedFiles.clear(); ohair@286: } ohair@286: } ohair@286: ohair@286: /** ohair@286: * Parses arguments and fill fields of this object. ohair@286: * ohair@286: * @exception BadCommandLineException ohair@286: * thrown when there's a problem in the command-line arguments ohair@286: */ ohair@286: public void parseArguments( String[] args ) throws BadCommandLineException { ohair@286: ohair@286: for (int i = 0; i < args.length; i++) { ohair@286: if(args[i].length()==0) ohair@286: throw new BadCommandLineException(); ohair@286: if (args[i].charAt(0) == '-') { ohair@286: int j = parseArguments(args,i); ohair@286: if(j==0) ohair@286: throw new BadCommandLineException(WscompileMessages.WSCOMPILE_INVALID_OPTION(args[i])); ohair@286: i += (j-1); ohair@286: } else { ohair@286: addFile(args[i]); ohair@286: } ohair@286: } ohair@286: if(destDir == null) ohair@286: destDir = new File("."); ohair@286: if(sourceDir == null) ohair@286: sourceDir = destDir; ohair@286: } ohair@286: ohair@286: ohair@286: /** ohair@286: * Adds a file from the argume ohair@286: * ohair@286: * @param arg a file, could be a wsdl or xsd or a Class ohair@286: */ ohair@286: protected void addFile(String arg) throws BadCommandLineException {} ohair@286: ohair@286: /** ohair@286: * Parses an option args[i] and return ohair@286: * the number of tokens consumed. ohair@286: * ohair@286: * @return ohair@286: * 0 if the argument is not understood. Returning 0 ohair@286: * will let the caller report an error. ohair@286: * @exception BadCommandLineException ohair@286: * If the callee wants to provide a custom message for an error. ohair@286: */ ohair@286: protected int parseArguments(String[] args, int i) throws BadCommandLineException { ohair@286: if (args[i].equals("-g")) { ohair@286: debug = true; ohair@286: return 1; ohair@286: } else if (args[i].equals("-Xdebug")) { ohair@286: debugMode = true; ohair@286: return 1; ohair@286: } else if (args[i].equals("-Xendorsed")) { ohair@286: // this option is processed much earlier, so just ignore. ohair@286: return 1; ohair@286: } else if (args[i].equals("-verbose")) { ohair@286: verbose = true; ohair@286: return 1; ohair@286: } else if (args[i].equals("-quiet")) { ohair@286: quiet = true; ohair@286: return 1; ohair@286: } else if (args[i].equals("-keep")) { ohair@286: keep = true; ohair@286: return 1; ohair@286: } else if (args[i].equals("-target")) { ohair@286: String token = requireArgument("-target", args, ++i); ohair@286: target = Target.parse(token); ohair@286: if(target == null) ohair@286: throw new BadCommandLineException(WscompileMessages.WSIMPORT_ILLEGAL_TARGET_VERSION(token)); ohair@286: return 2; ohair@286: } else if (args[i].equals("-classpath") || args[i].equals("-cp")) { ohair@286: classpath = requireArgument("-classpath", args, ++i) + File.pathSeparator + System.getProperty("java.class.path"); ohair@286: return 2; ohair@286: } else if (args[i].equals("-d")) { ohair@286: destDir = new File(requireArgument("-d", args, ++i)); ohair@286: if (!destDir.exists()) ohair@286: throw new BadCommandLineException(WscompileMessages.WSCOMPILE_NO_SUCH_DIRECTORY(destDir.getPath())); ohair@286: return 2; ohair@286: } else if (args[i].equals("-s")) { ohair@286: sourceDir = new File(requireArgument("-s", args, ++i)); ohair@286: keep = true; ohair@286: if (!sourceDir.exists()) { ohair@286: throw new BadCommandLineException(WscompileMessages.WSCOMPILE_NO_SUCH_DIRECTORY(sourceDir.getPath())); ohair@286: } ohair@286: return 2; ohair@286: } else if (args[i].equals("-extension")) { ohair@286: compatibilityMode = EXTENSION; ohair@286: return 1; ohair@286: } else if (args[i].startsWith("-help")) { ohair@286: WeAreDone done = new WeAreDone(); ohair@286: done.initOptions(this); ohair@286: throw done; ohair@286: } else if (args[i].equals("-Xnocompile")) { ohair@286: // -nocompile implies -keep. this is undocumented switch. ohair@286: nocompile = true; ohair@286: keep = true; ohair@286: return 1; ohair@286: } else if (args[i].equals("-encoding")) { ohair@286: encoding = requireArgument("-encoding", args, ++i); ohair@286: try { ohair@286: if (!Charset.isSupported(encoding)) { ohair@286: throw new BadCommandLineException(WscompileMessages.WSCOMPILE_UNSUPPORTED_ENCODING(encoding)); ohair@286: } ohair@286: } catch (IllegalCharsetNameException icne) { ohair@286: throw new BadCommandLineException(WscompileMessages.WSCOMPILE_UNSUPPORTED_ENCODING(encoding)); ohair@286: } ohair@286: return 2; mkos@408: } else if (args[i].equals("-disableXmlSecurity")) { mkos@408: disableXmlSecurity(); mkos@408: return 1; mkos@408: } else if (args[i].startsWith("-J")) { mkos@408: if (javacOptions == null) { mkos@408: javacOptions = new ArrayList(); mkos@408: } mkos@408: javacOptions.add(args[i].substring(2)); alanb@368: return 1; ohair@286: } ohair@286: return 0; ohair@286: } ohair@286: mkos@408: // protected method to allow overriding mkos@408: protected void disableXmlSecurity() { mkos@408: disableXmlSecurity= true; mkos@408: } mkos@408: ohair@286: /** ohair@286: * Obtains an operand and reports an error if it's not there. ohair@286: */ ohair@286: public String requireArgument(String optionName, String[] args, int i) throws BadCommandLineException { ohair@286: //if (i == args.length || args[i].startsWith("-")) { ohair@286: if (args[i].startsWith("-")) { ohair@286: throw new BadCommandLineException(WscompileMessages.WSCOMPILE_MISSING_OPTION_ARGUMENT(optionName)); ohair@286: } ohair@286: return args[i]; ohair@286: } ohair@286: mkos@408: List getJavacOptions(List existingOptions, WsimportListener listener) { mkos@408: List result = new ArrayList(); mkos@408: for (String o: javacOptions) { mkos@408: if (o.contains("=") && !o.startsWith("A")) { mkos@408: int i = o.indexOf('='); mkos@408: String key = o.substring(0, i); mkos@408: if (existingOptions.contains(key)) { mkos@408: listener.message(WscompileMessages.WSCOMPILE_EXISTING_OPTION(key)); mkos@408: } else { mkos@408: result.add(key); mkos@408: result.add(o.substring(i + 1)); mkos@408: } mkos@408: } else { mkos@408: if (existingOptions.contains(o)) { mkos@408: listener.message(WscompileMessages.WSCOMPILE_EXISTING_OPTION(o)); mkos@408: } else { mkos@408: result.add(o); mkos@408: } mkos@408: } mkos@408: } mkos@408: return result; mkos@408: } ohair@286: ohair@286: /** ohair@286: * Used to signal that we've finished processing. ohair@286: */ ohair@286: public static final class WeAreDone extends BadCommandLineException {} ohair@286: ohair@286: /** ohair@286: * Get a URLClassLoader from using the classpath ohair@286: */ ohair@286: public ClassLoader getClassLoader() { ohair@286: if (classLoader == null) { ohair@286: classLoader = ohair@286: new URLClassLoader(pathToURLs(classpath), ohair@286: this.getClass().getClassLoader()); ohair@286: } ohair@286: return classLoader; ohair@286: } ohair@286: ohair@286: /** ohair@286: * Utility method for converting a search path string to an array ohair@286: * of directory and JAR file URLs. ohair@286: * ohair@286: * @param path the search path string ohair@286: * @return the resulting array of directory and JAR file URLs ohair@286: */ ohair@286: public static URL[] pathToURLs(String path) { ohair@286: StringTokenizer st = new StringTokenizer(path, File.pathSeparator); ohair@286: URL[] urls = new URL[st.countTokens()]; ohair@286: int count = 0; ohair@286: while (st.hasMoreTokens()) { ohair@286: URL url = fileToURL(new File(st.nextToken())); ohair@286: if (url != null) { ohair@286: urls[count++] = url; ohair@286: } ohair@286: } ohair@286: if (urls.length != count) { ohair@286: URL[] tmp = new URL[count]; ohair@286: System.arraycopy(urls, 0, tmp, 0, count); ohair@286: urls = tmp; ohair@286: } ohair@286: return urls; ohair@286: } ohair@286: ohair@286: /** ohair@286: * Returns the directory or JAR file URL corresponding to the specified ohair@286: * local file name. ohair@286: * ohair@286: * @param file the File object ohair@286: * @return the resulting directory or JAR file URL, or null if unknown ohair@286: */ ohair@286: public static URL fileToURL(File file) { ohair@286: String name; ohair@286: try { ohair@286: name = file.getCanonicalPath(); ohair@286: } catch (IOException e) { ohair@286: name = file.getAbsolutePath(); ohair@286: } ohair@286: name = name.replace(File.separatorChar, '/'); ohair@286: if (!name.startsWith("/")) { ohair@286: name = "/" + name; ohair@286: } ohair@286: ohair@286: // If the file does not exist, then assume that it's a directory ohair@286: if (!file.isFile()) { ohair@286: name = name + "/"; ohair@286: } ohair@286: try { ohair@286: return new URL("file", "", name); ohair@286: } catch (MalformedURLException e) { ohair@286: throw new IllegalArgumentException("file"); ohair@286: } ohair@286: } ohair@286: ohair@286: }