src/share/jaxws_classes/com/sun/tools/internal/ws/processor/generator/JwsImplGenerator.java

Tue, 06 Mar 2012 16:09:35 -0800

author
ohair
date
Tue, 06 Mar 2012 16:09:35 -0800
changeset 286
f50545b5e2f1
child 368
0989ad8c0860
permissions
-rw-r--r--

7150322: Stop using drop source bundles in jaxws
Reviewed-by: darcy, ohrstrom

     1 /*
     2  * Copyright (c) 1997, 2011, 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  */
    26 package com.sun.tools.internal.ws.processor.generator;
    28 import com.sun.codemodel.internal.*;
    29 import com.sun.tools.internal.ws.processor.model.*;
    30 import com.sun.tools.internal.ws.processor.model.java.JavaInterface;
    31 import com.sun.tools.internal.ws.processor.model.java.JavaMethod;
    32 import com.sun.tools.internal.ws.processor.model.java.JavaParameter;
    33 import com.sun.tools.internal.ws.processor.model.jaxb.JAXBTypeAndAnnotation;
    34 import com.sun.tools.internal.ws.wsdl.document.Definitions;
    35 import com.sun.tools.internal.ws.wsdl.document.Binding;
    36 import com.sun.tools.internal.ws.wsdl.document.soap.SOAP12Binding;
    37 import com.sun.tools.internal.ws.wsdl.document.soap.SOAPBinding;
    38 import com.sun.tools.internal.ws.wsdl.document.soap.SOAPConstants;
    39 import com.sun.tools.internal.ws.api.wsdl.TWSDLExtension;
    40 import com.sun.tools.internal.ws.wscompile.ErrorReceiver;
    41 import com.sun.tools.internal.ws.processor.model.ModelProperties;
    42 import com.sun.tools.internal.ws.wscompile.WsimportOptions;
    43 import com.sun.codemodel.internal.JClassAlreadyExistsException;
    44 import com.sun.xml.internal.ws.api.SOAPVersion;
    46 import com.sun.xml.internal.ws.util.ServiceFinder;
    48 import javax.jws.WebService;
    49 import javax.xml.ws.BindingType;
    50 import javax.xml.namespace.QName;
    51 import javax.xml.ws.Holder;
    52 import java.io.File;
    53 import java.util.ArrayList;
    54 import java.util.HashMap;
    55 import java.util.List;
    56 import java.util.Iterator;
    57 import java.util.Map;
    59 /**
    60  * Generator for placeholder JWS implementations
    61  *
    62  * @since 2.2.6
    63  */
    64 public final class JwsImplGenerator extends GeneratorBase {
    65         private static final Map<String, String> TRANSLATION_MAP = new HashMap<String, String>(
    66       1);
    67         static
    68   {
    69     TRANSLATION_MAP.put(SOAPConstants.URI_SOAP_TRANSPORT_HTTP,
    70                 javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING);
    71   }
    72         // save the generated impl files' info
    73         private final List<String> implFiles = new ArrayList<String>();
    75         public static List<String> generate(Model model, WsimportOptions options,
    76             ErrorReceiver receiver) {
    77                 // options check
    79                 // Generate it according the implDestDir option
    80                 if (options.implDestDir == null)
    81                         return null;
    83                 JwsImplGenerator jwsImplGenerator = new JwsImplGenerator();
    84                 jwsImplGenerator.init(model, options, receiver);
    85                 jwsImplGenerator.doGeneration();
    86                 // print a warning message while implFiles.size() is zero
    87                 if (jwsImplGenerator.implFiles.size() == 0) {
    88                         StringBuffer msg = new StringBuffer();
    89                         if (options.implServiceName != null)
    90                                 msg.append("serviceName=[" + options.implServiceName + "] ");
    91                         if (options.implPortName != null)
    92                                 msg.append("portName=[" + options.implPortName + "] ");
    94                         if (msg.length() > 0)
    95                                 msg.append(", Not found in wsdl file.\n");
    97                         msg.append("No impl files generated!");
    98                         receiver.warning(null, msg.toString());
    99                 }
   101                 return jwsImplGenerator.implFiles;
   102         }
   104         /**
   105          * Move impl files to implDestDir
   106          */
   107         public static boolean moveToImplDestDir(List<String> gImplFiles,
   108             WsimportOptions options, ErrorReceiver receiver) {
   109                 if (options.implDestDir == null || gImplFiles == null
   110                     || gImplFiles.size() == 0)
   111                         return true;
   113                 List<ImplFile> generatedImplFiles = ImplFile.toImplFiles(gImplFiles);
   115                 try {
   116                         File implDestDir = makePackageDir(options);
   118                         File movedF;
   119                         File f;
   120                         for (ImplFile implF : generatedImplFiles) {
   121                                 movedF = findFile(options, implF.qualifiedName);
   122                                 if (movedF == null) {
   123                                         // should never happen
   124                                         receiver.warning(null, "Class " + implF.qualifiedName
   125                                             + " is not generated. Not moving.");
   126                                         return false;
   127                                 }
   129                                 f = new File(implDestDir, implF.name);
   130                             if (!movedF.equals(f)) {    //bug 10102169
   132                     if (f.exists())
   133                     {
   134                         if (!f.delete()){
   135                             receiver.error("Class " + implF.qualifiedName
   136                                     + " has existed in destImplDir, and it "
   137                                     + "can not be written!", null);
   138                         }
   139                     }
   140                     if(!movedF.renameTo(f))
   141                     {
   142                         throw new Exception();
   143                     }
   144                 }
   145                         }
   146                 } catch (Exception e) {
   147                         receiver.error("Moving WebService Impl files failed!", e);
   148                         return false;
   149                 }
   150                 return true;
   151         }
   153         private JwsImplGenerator() {
   154                 donotOverride = true;
   155         }
   157         @Override
   158         public void visit(Service service) {
   159                 QName serviceName = service.getName();
   160                 // process the ordered service only if it is defined
   161                 if (options.implServiceName != null
   162                     && !equalsNSOptional(options.implServiceName, serviceName))
   163                         return;
   165                 for (Port port : service.getPorts()) {
   166                         if (port.isProvider()) {
   167                                 continue; // Not generating for Provider based endpoint
   168                         }
   170                         // Generate the impl class name according to
   171                         // Xpath(/definitions/service/port[@name]);
   172                         QName portName = port.getName();
   174                         // process the ordered port only if it is defined
   175                         if (options.implPortName != null
   176                             && !equalsNSOptional(options.implPortName, portName))
   177                                 continue;
   179                         String simpleClassName = serviceName.getLocalPart() + "_"
   180                             + portName.getLocalPart() + "Impl";
   181                         String className = makePackageQualified(simpleClassName);
   182                         implFiles.add(className);
   184                         if (donotOverride && GeneratorUtil.classExists(options, className)) {
   185                                 log("Class " + className + " exists. Not overriding.");
   186                                 return;
   187                         }
   189                         JDefinedClass cls = null;
   190                         try {
   191                                 cls = getClass(className, ClassType.CLASS);
   192                         } catch (JClassAlreadyExistsException e) {
   193                                 log("Class " + className
   194                                     + " generates failed. JClassAlreadyExistsException[" + className
   195                                     + "].");
   196                                 return;
   197                         }
   199                         // Each serviceImpl will implements one port interface
   200                         JavaInterface portIntf = port.getJavaInterface();
   201                         String portClassName = Names.customJavaTypeClassName(portIntf);
   202                         JDefinedClass portCls = null;
   203                         try {
   204                                 portCls = getClass(portClassName, ClassType.INTERFACE);
   205                         } catch (JClassAlreadyExistsException e) {
   206                                 log("Class " + className
   207                                     + " generates failed. JClassAlreadyExistsException["
   208                                     + portClassName + "].");
   209                                 return;
   210                         }
   211                         cls._implements(portCls);
   213                         // create a default constructor
   214                         cls.constructor(JMod.PUBLIC);
   216                         // write class comment - JAXWS warning
   217                         JDocComment comment = cls.javadoc();
   219                         if (service.getJavaDoc() != null) {
   220                                 comment.add(service.getJavaDoc());
   221                                 comment.add("\n\n");
   222                         }
   224                         for (String doc : getJAXWSClassComment()) {
   225                                 comment.add(doc);
   226                         }
   228                         // @WebService
   229                         JAnnotationUse webServiceAnn = cls.annotate(cm.ref(WebService.class));
   230                         writeWebServiceAnnotation(service, port, webServiceAnn);
   232                         // @BindingType
   233                         JAnnotationUse bindingTypeAnn = cls.annotate(cm.ref(BindingType.class));
   234                         writeBindingTypeAnnotation(port, bindingTypeAnn);
   236                         // extra annotation
   237                         for( GeneratorExtension f : ServiceFinder.find(GeneratorExtension.class) ) {
   238                             f.writeWebServiceAnnotation(model, cm, cls, port);
   239                         }
   241                         // WebMethods
   242                         for (Operation operation : port.getOperations()) {
   243                                 JavaMethod method = operation.getJavaMethod();
   245                                 // @WebMethod
   246                                 JMethod m;
   247                                 JDocComment methodDoc;
   248                                 String methodJavaDoc = operation.getJavaDoc();
   249                                 if (method.getReturnType().getName().equals("void")) {
   250                                         m = cls.method(JMod.PUBLIC, void.class, method.getName());
   251                                         methodDoc = m.javadoc();
   252                                 } else {
   253                                         JAXBTypeAndAnnotation retType = method.getReturnType().getType();
   254                                         m = cls.method(JMod.PUBLIC, retType.getType(), method.getName());
   255                                         retType.annotate(m);
   256                                         methodDoc = m.javadoc();
   257                                         JCommentPart ret = methodDoc.addReturn();
   258                                         ret.add("returns " + retType.getName());
   259                                 }
   261                                 if (methodJavaDoc != null)
   262                                         methodDoc.add(methodJavaDoc);
   264                                 JClass holder = cm.ref(Holder.class);
   265                                 for (JavaParameter parameter : method.getParametersList()) {
   266                                         JVar var;
   267                                         JAXBTypeAndAnnotation paramType = parameter.getType().getType();
   268                                         if (parameter.isHolder()) {
   269                                                 var = m.param(holder.narrow(paramType.getType().boxify()),
   270                                                     parameter.getName());
   271                                         } else {
   272                                                 var = m.param(paramType.getType(), parameter.getName());
   273                                         }
   274                                         methodDoc.addParam(var);
   275                                 }
   277                                 com.sun.tools.internal.ws.wsdl.document.Operation wsdlOp = operation
   278                                     .getWSDLPortTypeOperation();
   279                                 for (Fault fault : operation.getFaultsSet()) {
   280                                         m._throws(fault.getExceptionClass());
   281                                         methodDoc.addThrows(fault.getExceptionClass());
   282                                         wsdlOp.putFault(fault.getWsdlFaultName(), fault.getExceptionClass());
   283                                 }
   284                                 m.body().block().directStatement("//replace with your impl here");
   285                                 m.body().block().directStatement(
   286                                     getReturnString(method.getReturnType().getName()));
   287                         }
   288                 }
   289         }
   291         /**
   292          * Generate return statement according to return type.
   293          *
   294          * @param type
   295          *          The method's return type
   296          * @return The whole return statement
   297          */
   298         private String getReturnString(String type) {
   299                 final String nullReturnStr = "return null;";
   300                 // complex type or array
   301                 if (type.indexOf('.') > -1 || type.indexOf('[') > -1) {
   302                         return nullReturnStr;
   303                 }
   305                 // primitive type
   306                 if (type.equals("void")) {
   307                         return "return;";
   308                 }
   309                 if (type.equals("boolean")) {
   310                         return "return false;";
   311                 }
   312                 if (type.equals("int") || type.equals("byte") || type.equals("short")
   313                     || type.equals("long") || type.equals("double") || type.equals("float")) {
   314                         return "return 0;";
   315                 }
   316                 if (type.equals("char")) {
   317                         return "return '0';";
   318                 }
   320                 return nullReturnStr;
   321         }
   323         /**
   324          *
   325          * @param service
   326          * @param port
   327          * @param webServiceAnn
   328          * @param options
   329          */
   330         private void writeWebServiceAnnotation(Service service, Port port,
   331             JAnnotationUse webServiceAnn) {
   332                 webServiceAnn.param("portName", port.getName().getLocalPart());
   333                 webServiceAnn.param("serviceName", service.getName().getLocalPart());
   334                 webServiceAnn.param("targetNamespace", service.getName().getNamespaceURI());
   335                 webServiceAnn.param("wsdlLocation", wsdlLocation);
   336                 webServiceAnn.param("endpointInterface", port.getJavaInterface().getName());
   337         }
   338         //CR373098 To transform the java class name as validate.
   339   private String transToValidJavaIdentifier(String s) {
   340     if (s == null) return null;
   341     final int len = s.length();
   342     StringBuffer retSB = new StringBuffer();
   343     if (len == 0 || !Character.isJavaIdentifierStart(s.charAt(0)))
   344       retSB.append("J"); //update to a default start char
   345     else
   346         retSB.append(s.charAt(0));
   348     for (int i = 1; i < len; i++) {
   349       if (!Character.isJavaIdentifierPart(s.charAt(i)))
   350         ;  //delete it if it is illegal //TODO: It might conflict "a-b" vs. "ab"
   351       else
   352         retSB.append(s.charAt(i));
   353     }
   354     return retSB.toString();
   355   }
   357         private String makePackageQualified(String s) {
   358                 s = transToValidJavaIdentifier(s);
   359                 if (options.defaultPackage != null && !options.defaultPackage.equals("")) {
   360                         return options.defaultPackage + "." + s;
   361                 } else {
   362                         return s;
   363                 }
   364         }
   367         /**
   368          * TODO
   369          *
   370          * @param port
   371          * @param bindingTypeAnn
   372          */
   373         private void writeBindingTypeAnnotation(Port port,
   374             JAnnotationUse bindingTypeAnn) {
   375                 QName bName = (QName) port
   376                     .getProperty(ModelProperties.PROPERTY_WSDL_BINDING_NAME);
   377                 if (bName == null)
   378                         return;
   380                 String v = getBindingType(bName);
   382                 // TODO: How to decide if it is a mtom?
   383                 if (v != null) {
   384                         // transport = translate(transport);
   385                         bindingTypeAnn.param("value", v);
   386                 }
   388         }
   390         private String resolveBindingValue(TWSDLExtension wsdlext) {
   391                 if (wsdlext.getClass().equals(SOAPBinding.class)) {
   392                         SOAPBinding sb = (SOAPBinding) wsdlext;
   393                         if(javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING.equals(sb.getTransport()))
   394                                 return javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_MTOM_BINDING;
   395                         else {
   396                             for(GeneratorExtension f : ServiceFinder.find(GeneratorExtension.class) ) {
   397                                 String bindingValue = f.getBindingValue(sb.getTransport(), SOAPVersion.SOAP_11);
   398                                 if(bindingValue!=null) {
   399                                     return bindingValue;
   400                                 }
   401                             }
   402                                 return javax.xml.ws.soap.SOAPBinding.SOAP11HTTP_BINDING;
   403                         }
   404                 }
   405                 if (wsdlext.getClass().equals(SOAP12Binding.class)) {
   406                         SOAP12Binding sb = (SOAP12Binding) wsdlext;
   407                         if(javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING.equals(sb.getTransport()))
   408                                 return javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_MTOM_BINDING;
   409                     else {
   410                         for(GeneratorExtension f : ServiceFinder.find(GeneratorExtension.class) ) {
   411                             String bindingValue = f.getBindingValue(sb.getTransport(), SOAPVersion.SOAP_12);
   412                             if(bindingValue!=null) {
   413                                 return bindingValue;
   414                             }
   415                         }
   416                             return javax.xml.ws.soap.SOAPBinding.SOAP12HTTP_BINDING;
   417                     }
   418                 }
   419                 return null;
   420         }
   422         private String getBindingType(QName bName) {
   424                 String value = null;
   425                 // process the bindings in definitions of model.entity
   426                 if (model.getEntity() instanceof Definitions) {
   427                         Definitions definitions = (Definitions) model.getEntity();
   428                         if (definitions != null) {
   429                                 Iterator bindings = definitions.bindings();
   430                                 if (bindings != null) {
   431                                         while (bindings.hasNext()) {
   432                                                 Binding binding = (Binding) bindings.next();
   433                                                 if (bName.getLocalPart().equals(binding.getName())
   434                                                     && bName.getNamespaceURI().equals(binding.getNamespaceURI())) {
   435                                                         List<TWSDLExtension> bindextends = (List<TWSDLExtension>) binding
   436                                                             .extensions();
   437                                                         for (TWSDLExtension wsdlext : bindextends) {
   438                                                                 value = resolveBindingValue(wsdlext);
   439                                                                 if (value != null)
   440                                                                         break;
   441                                                         }
   442                                                         break;
   443                                                 }
   444                                         }
   445                                 }
   446                         }
   447                 }
   449                 // process the bindings in backup list of model
   450                 if (value == null) {
   451                         // TODO: The property "BAKEUP_BINDINGS" is set in WsdlModeler when init
   452                         // the model
   453                         // make this as a const if needed.
   454                         HashMap hm = (HashMap) model.getProperty("BAKEUP_BINDINGS");
   455                         Binding b = (Binding) hm.get(bName);
   456                         if (b != null) {
   457                                 List<TWSDLExtension> bindextends = (List<TWSDLExtension>) b
   458                                     .extensions();
   459                                 for (TWSDLExtension wsdlext : bindextends) {
   460                                         value = resolveBindingValue(wsdlext);
   461                                         if (value != null)
   462                                                 break;
   463                                 }
   464                         }
   465                 }
   467                 return value;
   468         }
   470   /**
   471    * Since the SOAP 1.1 binding transport URI defined in WSDL 1.1 specification
   472    * is different with the SOAPBinding URI defined by JAX-WS 2.0 specification.
   473    * We must translate the wsdl version into JAX-WS version. If the given
   474    * transport URI is NOT one of the predefined transport URIs, it is returned
   475    * as is.
   476    *
   477    * @param transportURI
   478    *          retrieved from WSDL
   479    * @return Standard BindingType URI defined by JAX-WS 2.0 specification.
   480    */
   481   private String translate(String transportURI)
   482   {
   483     String translatedBindingId = TRANSLATION_MAP.get(transportURI);
   484     if (translatedBindingId == null)
   485       translatedBindingId = transportURI;
   487     return translatedBindingId;
   488   }
   490         /*****************************************************************************
   491          * Inner classes definition
   492          */
   493         static final class ImplFile {
   494                 public String qualifiedName; // package+"."+simpleClassName + ".java"
   496                 public String name; // simpleClassName + ".java"
   498                 private ImplFile(String qualifiedClassName) {
   499                         this.qualifiedName = qualifiedClassName + ".java";
   501                         String simpleClassName = qualifiedClassName;
   502                         int i = qualifiedClassName.lastIndexOf(".");
   503                         if (i != -1)
   504                                 simpleClassName = qualifiedClassName.substring(i + 1);
   506                         this.name = simpleClassName + ".java";
   507                 }
   509                 public static List<ImplFile> toImplFiles(List<String> qualifiedClassNames) {
   510                         List<ImplFile> ret = new ArrayList<ImplFile>();
   512                         for (String qualifiedClassName : qualifiedClassNames)
   513                                 ret.add(new ImplFile(qualifiedClassName));
   515                         return ret;
   516                 }
   517         }
   519         /*****************************************************************************
   520          * Other utility methods
   521          */
   523         private static File makePackageDir(WsimportOptions options) {
   524                 File ret = null;
   525                 if (options.defaultPackage != null && !options.defaultPackage.equals("")) {
   526                         String subDir = options.defaultPackage.replace('.', '/');
   527                         ret = new File(options.implDestDir, subDir);
   528                 } else {
   529                         ret = options.implDestDir;
   530                 }
   532                 ret.mkdirs();
   533                 return ret;
   534         }
   536         private static String getQualifiedFileName(String canonicalBaseDir, File f)
   537             throws java.io.IOException {
   538                 String fp = f.getCanonicalPath();
   539                 if (fp == null)
   540                         return null;
   541                 fp = fp.replace(canonicalBaseDir, "");
   542                 fp = fp.replace('\\', '.');
   543                 fp = fp.replace('/', '.');
   544                 if (fp.startsWith("."))
   545                         fp = fp.substring(1);
   547                 return fp;
   548         }
   550         private static File findFile(WsimportOptions options, String qualifiedFileName)
   551             throws java.io.IOException {
   552                 String baseDir = options.destDir.getCanonicalPath();
   553                 String fp = null;
   554                 for (File f : options.getGeneratedFiles()) {
   555                         fp = getQualifiedFileName(baseDir, f);
   556                         if (qualifiedFileName.equals(fp))
   557                                 return f;
   558                 }
   560                 return null;
   561         }
   563         private static boolean equalsNSOptional(String strQName, QName checkQN) {
   564                 if (strQName == null)
   565                         return false;
   566                 strQName = strQName.trim();
   567                 QName reqQN = QName.valueOf(strQName);
   569                 if (reqQN.getNamespaceURI() == null || reqQN.getNamespaceURI().equals(""))
   570                         return reqQN.getLocalPart().equals(checkQN.getLocalPart());
   572                 return reqQN.equals(checkQN);
   573         }
   574 }

mercurial