1 /*
   2  * Copyright (c) 1997, 2012, 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.api.WsgenExtension;
  29 import com.sun.tools.internal.ws.api.WsgenProtocol;
  30 import com.sun.tools.internal.ws.resources.WscompileMessages;
  31 import com.sun.xml.internal.ws.api.BindingID;
  32 import com.sun.xml.internal.ws.binding.SOAPBindingImpl;
  33 import com.sun.xml.internal.ws.util.ServiceFinder;
  34 
  35 import javax.jws.WebService;
  36 import javax.xml.namespace.QName;
  37 import java.io.File;
  38 import java.util.ArrayList;
  39 import java.util.LinkedHashMap;
  40 import java.util.LinkedHashSet;
  41 import java.util.List;
  42 import java.util.Map;
  43 import java.util.Set;
  44 
  45 /**
  46  * @author Vivek Pandey
  47  */
  48 public class WsgenOptions extends Options {
  49     /**
  50      * -servicename
  51      */
  52     public QName serviceName;
  53 
  54     /**
  55      * -portname
  56      */
  57     public QName portName;
  58 
  59     /**
  60      * -r
  61      */
  62     public File nonclassDestDir;
  63 
  64 
  65     /**
  66      * -wsdl
  67      */
  68     public boolean genWsdl;
  69 
  70     /**
  71      * -inlineSchemas
  72      */
  73     public boolean inlineSchemas;
  74 
  75     /**
  76      * protocol value
  77      */
  78     public String protocol = "soap1.1";
  79 
  80     public Set<String> protocols = new LinkedHashSet<String>();
  81     public Map<String, String> nonstdProtocols = new LinkedHashMap<String, String>();
  82 
  83     /**
  84      * -XwsgenReport
  85      */
  86     public File wsgenReport;
  87 
  88     /**
  89      * -Xdonotoverwrite
  90      */
  91     public boolean doNotOverWrite;
  92 
  93     /**
  94      * Tells if user specified a specific protocol
  95      */
  96     public boolean protocolSet = false;
  97 
  98     /**
  99      * <code>-x file1 -x file2 ...<code/><br />
 100      * Files to be parsed to get classes' metadata in addition/instead of using annotations and reflection API
 101      */
 102     public List<String> externalMetadataFiles = new ArrayList<String>();
 103 
 104     private static final String SERVICENAME_OPTION = "-servicename";
 105     private static final String PORTNAME_OPTION = "-portname";
 106     private static final String HTTP   = "http";
 107     private static final String SOAP11 = "soap1.1";
 108     public static final String X_SOAP12 = "Xsoap1.2";
 109 
 110     public WsgenOptions() {
 111         protocols.add(SOAP11);
 112         protocols.add(X_SOAP12);
 113         nonstdProtocols.put(X_SOAP12, SOAPBindingImpl.X_SOAP12HTTP_BINDING);
 114         ServiceFinder<WsgenExtension> extn = ServiceFinder.find(WsgenExtension.class);
 115         for(WsgenExtension ext : extn) {
 116             Class clazz = ext.getClass();
 117             WsgenProtocol pro = (WsgenProtocol)clazz.getAnnotation(WsgenProtocol.class);
 118             protocols.add(pro.token());
 119             nonstdProtocols.put(pro.token(), pro.lexical());
 120         }
 121     }
 122 
 123     @Override
 124     protected int parseArguments(String[] args, int i) throws BadCommandLineException {
 125 
 126         int j = super.parseArguments(args, i);
 127         if (args[i].equals(SERVICENAME_OPTION)) {
 128             serviceName = QName.valueOf(requireArgument(SERVICENAME_OPTION, args, ++i));
 129             if (serviceName.getNamespaceURI() == null || serviceName.getNamespaceURI().length() == 0) {
 130                 throw new BadCommandLineException(WscompileMessages.WSGEN_SERVICENAME_MISSING_NAMESPACE(args[i]));
 131             }
 132             if (serviceName.getLocalPart() == null || serviceName.getLocalPart().length() == 0) {
 133                 throw new BadCommandLineException(WscompileMessages.WSGEN_SERVICENAME_MISSING_LOCALNAME(args[i]));
 134             }
 135             return 2;
 136         } else if (args[i].equals(PORTNAME_OPTION)) {
 137             portName = QName.valueOf(requireArgument(PORTNAME_OPTION, args, ++i));
 138             if (portName.getNamespaceURI() == null || portName.getNamespaceURI().length() == 0) {
 139                 throw new BadCommandLineException(WscompileMessages.WSGEN_PORTNAME_MISSING_NAMESPACE(args[i]));
 140             }
 141             if (portName.getLocalPart() == null || portName.getLocalPart().length() == 0) {
 142                 throw new BadCommandLineException(WscompileMessages.WSGEN_PORTNAME_MISSING_LOCALNAME(args[i]));
 143             }
 144             return 2;
 145         } else if (args[i].equals("-r")) {
 146             nonclassDestDir = new File(requireArgument("-r", args, ++i));
 147             if (!nonclassDestDir.exists()) {
 148                 throw new BadCommandLineException(WscompileMessages.WSCOMPILE_NO_SUCH_DIRECTORY(nonclassDestDir.getPath()));
 149             }
 150             return 2;
 151         } else if (args[i].startsWith("-wsdl")) {
 152             genWsdl = true;
 153             //String value = requireArgument("-wsdl", args, ++i).substring(5);
 154             String value = args[i].substring(5);
 155             int index = value.indexOf(':');
 156             if (index == 0) {
 157                 value = value.substring(1);
 158                 index = value.indexOf('/');
 159                 if (index == -1) {
 160                     protocol = value;
 161                 } else {
 162                     protocol = value.substring(0, index);
 163                 }
 164                 protocolSet = true;
 165             }
 166             return 1;
 167         } else if (args[i].equals("-XwsgenReport")) {
 168             // undocumented switch for the test harness
 169             wsgenReport = new File(requireArgument("-XwsgenReport", args, ++i));
 170             return 2;
 171         } else if (args[i].equals("-Xdonotoverwrite")) {
 172             doNotOverWrite = true;
 173             return 1;
 174         } else if (args[i].equals("-inlineSchemas")) {
 175             inlineSchemas = true;
 176             return 1;
 177         } else if ("-x".equals(args[i])) {
 178             externalMetadataFiles.add(requireArgument("-x", args, ++i));
 179             return 1;
 180         }
 181 
 182         return j;
 183     }
 184 
 185 
 186     @Override
 187     protected void addFile(String arg) {
 188         endpoints.add(arg);
 189     }
 190 
 191     List<String> endpoints = new ArrayList<String>();
 192 
 193     public Class endpoint;
 194 
 195 
 196     private boolean isImplClass;
 197 
 198     public void validate() throws BadCommandLineException {
 199         if(nonclassDestDir == null)
 200             nonclassDestDir = destDir;
 201 
 202         if (!protocols.contains(protocol)) {
 203             throw new BadCommandLineException(WscompileMessages.WSGEN_INVALID_PROTOCOL(protocol, protocols));
 204         }
 205 
 206         if (endpoints.isEmpty()) {
 207             throw new BadCommandLineException(WscompileMessages.WSGEN_MISSING_FILE());
 208         }
 209         if (protocol == null || protocol.equalsIgnoreCase(X_SOAP12) && !isExtensionMode()) {
 210             throw new BadCommandLineException(WscompileMessages.WSGEN_SOAP_12_WITHOUT_EXTENSION());
 211         }
 212 
 213         if (nonstdProtocols.containsKey(protocol) && !isExtensionMode()) {
 214             throw new BadCommandLineException(WscompileMessages.WSGEN_PROTOCOL_WITHOUT_EXTENSION(protocol));
 215         }
 216         if (inlineSchemas && !genWsdl) {
 217             throw new BadCommandLineException(WscompileMessages.WSGEN_INLINE_SCHEMAS_ONLY_WITH_WSDL());
 218         }
 219 
 220         validateEndpointClass();
 221         validateArguments();
 222     }
 223     /**
 224      * Get an implementation class annotated with @WebService annotation.
 225      */
 226     private void validateEndpointClass() throws BadCommandLineException {
 227         Class clazz = null;
 228         for(String cls : endpoints){
 229             clazz = getClass(cls);
 230             if (clazz == null)
 231                 continue;
 232 
 233             if (clazz.isEnum() || clazz.isInterface() ||
 234                 clazz.isPrimitive()) {
 235                 continue;
 236             }
 237             isImplClass = true;
 238             WebService webService = (WebService) clazz.getAnnotation(WebService.class);
 239             if(webService == null)
 240                 continue;
 241             break;
 242         }
 243         if(clazz == null){
 244             throw new BadCommandLineException(WscompileMessages.WSGEN_CLASS_NOT_FOUND(endpoints.get(0)));
 245         }
 246         if(!isImplClass){
 247             throw new BadCommandLineException(WscompileMessages.WSGEN_CLASS_MUST_BE_IMPLEMENTATION_CLASS(clazz.getName()));
 248         }
 249         endpoint = clazz;
 250         validateBinding();
 251     }
 252 
 253     private void validateBinding() throws BadCommandLineException {
 254         if (genWsdl) {
 255             BindingID binding = BindingID.parse(endpoint);
 256             if ((binding.equals(BindingID.SOAP12_HTTP) ||
 257                  binding.equals(BindingID.SOAP12_HTTP_MTOM)) &&
 258                     !(protocol.equals(X_SOAP12) && isExtensionMode())) {
 259                 throw new BadCommandLineException(WscompileMessages.WSGEN_CANNOT_GEN_WSDL_FOR_SOAP_12_BINDING(binding.toString(), endpoint.getName()));
 260             }
 261             if (binding.equals(BindingID.XML_HTTP)) {
 262                 throw new BadCommandLineException(WscompileMessages.WSGEN_CANNOT_GEN_WSDL_FOR_NON_SOAP_BINDING(binding.toString(), endpoint.getName()));
 263             }
 264         }
 265     }
 266 
 267     private void validateArguments() throws BadCommandLineException {
 268         if (!genWsdl) {
 269             if (serviceName != null) {
 270                 throw new BadCommandLineException(WscompileMessages.WSGEN_WSDL_ARG_NO_GENWSDL(SERVICENAME_OPTION));
 271             }
 272             if (portName != null) {
 273                 throw new BadCommandLineException(WscompileMessages.WSGEN_WSDL_ARG_NO_GENWSDL(PORTNAME_OPTION));
 274             }
 275         }
 276     }
 277 
 278     BindingID getBindingID(String protocol) {
 279         if (protocol.equals(SOAP11))
 280             return BindingID.SOAP11_HTTP;
 281         if (protocol.equals(X_SOAP12))
 282             return BindingID.SOAP12_HTTP;
 283         String lexical = nonstdProtocols.get(protocol);
 284         return (lexical != null) ? BindingID.parse(lexical) : null;
 285     }
 286 
 287 
 288     private Class getClass(String className) {
 289         try {
 290             return getClassLoader().loadClass(className);
 291         } catch (ClassNotFoundException e) {
 292             return null;
 293         }
 294     }
 295 
 296 }