1/*
2 * Copyright (c) 1997, 2017, 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
26package com.sun.xml.internal.ws.model;
27
28import com.sun.istack.internal.NotNull;
29import com.sun.istack.internal.localization.Localizable;
30import com.sun.xml.internal.ws.api.BindingID;
31import com.sun.xml.internal.ws.api.SOAPVersion;
32import com.sun.xml.internal.ws.api.WSBinding;
33import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
34import com.sun.xml.internal.ws.api.databinding.MetadataReader;
35import com.sun.xml.internal.ws.api.model.ExceptionType;
36import com.sun.xml.internal.ws.api.model.MEP;
37import com.sun.xml.internal.ws.api.model.Parameter;
38import com.sun.xml.internal.ws.api.model.ParameterBinding;
39import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
40import com.sun.xml.internal.ws.api.model.wsdl.WSDLInput;
41import com.sun.xml.internal.ws.api.model.wsdl.WSDLPart;
42import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
43import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
44import com.sun.xml.internal.ws.model.soap.SOAPBindingImpl;
45import com.sun.xml.internal.ws.resources.ModelerMessages;
46import com.sun.xml.internal.ws.resources.ServerMessages;
47import com.sun.xml.internal.ws.spi.db.BindingContext;
48import com.sun.xml.internal.ws.spi.db.TypeInfo;
49import com.sun.xml.internal.ws.spi.db.WrapperComposite;
50
51import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion;
52import static com.sun.xml.internal.ws.model.Utils.REFLECTION_NAVIGATOR;
53
54import javax.jws.*;
55import javax.jws.WebParam.Mode;
56import javax.jws.soap.SOAPBinding;
57import javax.jws.soap.SOAPBinding.Style;
58import javax.xml.bind.annotation.XmlElement;
59import javax.xml.bind.annotation.XmlSeeAlso;
60import javax.xml.namespace.QName;
61import javax.xml.ws.*;
62import javax.xml.ws.soap.MTOM;
63import javax.xml.ws.soap.MTOMFeature;
64import java.lang.annotation.Annotation;
65import java.lang.reflect.Method;
66import java.lang.reflect.Modifier;
67import java.lang.reflect.ParameterizedType;
68import java.lang.reflect.Type;
69import java.security.AccessController;
70import java.util.HashSet;
71import java.util.Map;
72import java.util.Set;
73import java.util.StringTokenizer;
74import java.util.TreeMap;
75import java.util.concurrent.Future;
76import java.util.logging.Logger;
77
78import static javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
79
80/**
81 * Creates a runtime model of a SEI (portClass).
82 *
83 * @author WS Developement Team
84 */
85public class RuntimeModeler {
86    private final WebServiceFeatureList features;
87    private BindingID bindingId;
88    private WSBinding wsBinding;
89    private final Class portClass;
90    private AbstractSEIModelImpl model;
91    private SOAPBindingImpl defaultBinding;
92    // can be empty but never null
93    private String packageName;
94    private String targetNamespace;
95    private boolean isWrapped = true;
96    private ClassLoader classLoader;
97    private final WSDLPort binding;
98    private QName serviceName;
99    private QName portName;
100    private Set<Class> classUsesWebMethod;
101    private DatabindingConfig config;
102    private MetadataReader metadataReader;
103    /**
104     *
105     */
106    public static final String PD_JAXWS_PACKAGE_PD  = ".jaxws.";
107    /**
108     *
109     */
110    public static final String JAXWS_PACKAGE_PD     = "jaxws.";
111    public static final String RESPONSE             = "Response";
112    public static final String RETURN               = "return";
113    public static final String BEAN                 = "Bean";
114    public static final String SERVICE              = "Service";
115    public static final String PORT                 = "Port";
116    public static final Class HOLDER_CLASS = Holder.class;
117    public static final String REMOTE_EXCEPTION_CLASS = "java.rmi.RemoteException";
118    public static final Class<RuntimeException> RUNTIME_EXCEPTION_CLASS = RuntimeException.class;
119    public static final Class<Exception> EXCEPTION_CLASS = Exception.class;
120    public static final String DecapitalizeExceptionBeanProperties = "com.sun.xml.internal.ws.api.model.DecapitalizeExceptionBeanProperties";
121    public static final String SuppressDocLitWrapperGeneration = "com.sun.xml.internal.ws.api.model.SuppressDocLitWrapperGeneration";
122    public static final String DocWrappeeNamespapceQualified = "com.sun.xml.internal.ws.api.model.DocWrappeeNamespapceQualified";
123
124  /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull BindingID bindingId, @NotNull WebServiceFeature... features) {
125        this(portClass, serviceName, null, bindingId, features);
126    }*/
127
128    /**
129     *
130     * creates an instance of RunTimeModeler given a <code>sei</code> and <code>binding</code>
131     * @param portClass The SEI class to be modeled.
132     * @param serviceName The ServiceName to use instead of one calculated from the implementation class
133     * @param wsdlPort {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLPort}
134     * @param features web service features
135     */
136  /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull WSDLPortImpl wsdlPort, @NotNull WebServiceFeature... features){
137        this(portClass, serviceName, wsdlPort, wsdlPort.getBinding().getBindingId(), features);
138    }*/
139
140  /*private RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, WSDLPortImpl binding, BindingID bindingId, @NotNull WebServiceFeature... features) {
141        this.portClass = portClass;
142        this.serviceName = serviceName;
143        this.binding = binding;
144        this.bindingId = bindingId;
145        this.features = features;
146    }*/
147
148    public RuntimeModeler(@NotNull DatabindingConfig config){
149        this.portClass = (config.getEndpointClass() != null)? config.getEndpointClass() : config.getContractClass();
150        this.serviceName = config.getMappingInfo().getServiceName();
151        this.binding = config.getWsdlPort();
152        this.classLoader = config.getClassLoader();
153        this.portName = config.getMappingInfo().getPortName();
154        this.config = config;
155        this.wsBinding = config.getWSBinding();
156        metadataReader = config.getMetadataReader();
157        targetNamespace = config.getMappingInfo().getTargetNamespace();
158        if (metadataReader == null) metadataReader = new ReflectAnnotationReader();
159        if (wsBinding != null) {
160            this.bindingId = wsBinding.getBindingId();
161                if (config.getFeatures() != null) wsBinding.getFeatures().mergeFeatures(config.getFeatures(), false);
162                if (binding != null) wsBinding.getFeatures().mergeFeatures(binding.getFeatures(), false);
163                this.features = WebServiceFeatureList.toList(wsBinding.getFeatures());
164        } else {
165            this.bindingId = config.getMappingInfo().getBindingID();
166            this.features = WebServiceFeatureList.toList(config.getFeatures());
167            if (binding != null) bindingId = binding.getBinding().getBindingId();
168            if (bindingId == null) bindingId = getDefaultBindingID();
169            if (!features.contains(MTOMFeature.class)) {
170                MTOM mtomAn = getAnnotation(portClass, MTOM.class);
171                if (mtomAn != null) features.add(WebServiceFeatureList.getFeature(mtomAn));
172            }
173            if (!features.contains(com.oracle.webservices.internal.api.EnvelopeStyleFeature.class)) {
174                com.oracle.webservices.internal.api.EnvelopeStyle es = getAnnotation(portClass, com.oracle.webservices.internal.api.EnvelopeStyle.class);
175                if (es != null) features.add(WebServiceFeatureList.getFeature(es));
176            }
177            this.wsBinding = bindingId.createBinding(features);
178        }
179    }
180
181    private BindingID getDefaultBindingID() {
182        BindingType bt = getAnnotation(portClass, BindingType.class);
183        if (bt != null) return BindingID.parse(bt.value());
184        SOAPVersion ver = getSoapVersion(features);
185        boolean mtomEnabled = features.isEnabled(MTOMFeature.class);
186        if (SOAPVersion.SOAP_12.equals(ver)) {
187            return (mtomEnabled) ? BindingID.SOAP12_HTTP_MTOM : BindingID.SOAP12_HTTP;
188        } else {
189            return (mtomEnabled) ? BindingID.SOAP11_HTTP_MTOM : BindingID.SOAP11_HTTP;
190        }
191        }
192
193        /**
194     * sets the classloader to be used when loading classes by the <code>RuntimeModeler</code>.
195     * @param classLoader ClassLoader used to load classes
196     */
197    public void setClassLoader(ClassLoader classLoader) {
198        this.classLoader = classLoader;
199    }
200
201    /**
202     * sets the PortName to be used by the <code>RuntimeModeler</code>.
203     * @param portName The PortName to be used instead of the PortName
204     * retrieved via annotations
205     */
206    public void setPortName(QName portName) {
207        this.portName = portName;
208    }
209
210    private <T extends Annotation> T getAnnotation(final Class<?> clazz, final Class<T> T) {
211        return metadataReader.getAnnotation(T, clazz);
212    }
213
214    private <T extends Annotation> T getAnnotation(final Method method, final Class<T> T) {
215        return metadataReader.getAnnotation(T, method);
216    }
217
218    private Annotation[] getAnnotations(final Method method) {
219        return metadataReader.getAnnotations(method);
220    }
221
222    private Annotation[] getAnnotations(final Class<?> c) {
223        return metadataReader.getAnnotations(c);
224    }
225    private Annotation[][] getParamAnnotations(final Method method) {
226        return metadataReader.getParameterAnnotations(method);
227    }
228
229    private static final Logger logger =
230        Logger.getLogger(
231            com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server");
232
233    //currently has many local vars which will be eliminated after debugging issues
234    //first draft
235    /**
236     * builds the runtime model from the <code>portClass</code> using the binding ID <code>bindingId</code>.
237     * @return the runtime model for the <code>portClass</code>.
238     */
239    public AbstractSEIModelImpl buildRuntimeModel() {
240        model = new SOAPSEIModel(features);
241        model.contractClass = config.getContractClass();
242        model.endpointClass = config.getEndpointClass();
243        model.classLoader = this.classLoader;
244        model.wsBinding = wsBinding;
245        model.databindingInfo.setWsdlURL(config.getWsdlURL());
246        model.databindingInfo.properties().putAll(config.properties());
247        if (model.contractClass == null) model.contractClass = portClass;
248        if (model.endpointClass == null && !portClass.isInterface()) model.endpointClass = portClass;
249        Class<?> seiClass = portClass;
250        metadataReader.getProperties(model.databindingInfo.properties(), portClass);
251        WebService webService = getAnnotation(portClass, WebService.class);
252        if (webService == null) {
253            throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
254                portClass.getCanonicalName());
255        }
256        Class<?> seiFromConfig = configEndpointInterface();
257        if (webService.endpointInterface().length() > 0 || seiFromConfig != null) {
258                if (seiFromConfig != null) {
259                        seiClass = seiFromConfig;
260                } else {
261                        seiClass = getClass(webService.endpointInterface(), ModelerMessages.localizableRUNTIME_MODELER_CLASS_NOT_FOUND(webService.endpointInterface()));
262                }
263            model.contractClass = seiClass;
264                model.endpointClass = portClass;
265            WebService seiService = getAnnotation(seiClass, WebService.class);
266            if (seiService == null) {
267                throw new RuntimeModelerException("runtime.modeler.endpoint.interface.no.webservice",
268                    webService.endpointInterface());
269            }
270
271            //check if @SOAPBinding is defined on the impl class
272            SOAPBinding sbPortClass = getAnnotation(portClass, SOAPBinding.class);
273            SOAPBinding sbSei = getAnnotation(seiClass, SOAPBinding.class);
274            if(sbPortClass != null){
275                if(sbSei == null || sbSei.style() != sbPortClass.style()|| sbSei.use() != sbPortClass.use()){
276                    logger.warning(ServerMessages.RUNTIMEMODELER_INVALIDANNOTATION_ON_IMPL("@SOAPBinding", portClass.getName(), seiClass.getName()));
277                }
278            }
279        }
280        if (serviceName == null)
281            serviceName = getServiceName(portClass, metadataReader);
282        model.setServiceQName(serviceName);
283
284//        String portLocalName  = portClass.getSimpleName()+PORT;
285//        if (webService.portName().length() >0) {
286//            portLocalName = webService.portName();
287//        } else if (webService.name().length() >0) {
288//            portLocalName = webService.name()+PORT;
289//        }
290//
291//        if (portName == null)
292//            portName = new QName(serviceName.getNamespaceURI(), portLocalName);
293//        if (!portName.getNamespaceURI().equals(serviceName.getNamespaceURI())) {
294//            throw new RuntimeModelerException("runtime.modeler.portname.servicename.namespace.mismatch",
295//                serviceName, portName);
296//        }
297
298        if (portName == null) portName = getPortName(portClass, metadataReader, serviceName.getNamespaceURI());
299        model.setPortName(portName);
300
301        // Check if databinding is overridden in annotation.
302        com.oracle.webservices.internal.api.databinding.DatabindingMode dbm2 = getAnnotation(portClass, com.oracle.webservices.internal.api.databinding.DatabindingMode.class);
303        if (dbm2 != null) model.databindingInfo.setDatabindingMode(dbm2.value());
304
305        processClass(seiClass);
306        if (model.getJavaMethods().size() == 0)
307            throw new RuntimeModelerException("runtime.modeler.no.operations",
308                    portClass.getName());
309        model.postProcess();
310
311        // Make the configured databinding mode available to the
312        // DatabindingConfig.
313        config.properties().put(BindingContext.class.getName(),
314                model.bindingContext);
315
316        // TODO: this needs to be fixed properly --
317        // when we are building RuntimeModel first before building WSDLModel,
318        // we still need to do this correctly
319        if(binding!=null)
320            model.freeze(binding);
321        return model;
322    }
323
324    private Class configEndpointInterface() {
325                if (config.getEndpointClass() == null ||
326                    config.getEndpointClass().isInterface()     ) return null; //client proxy Interface
327                return config.getContractClass();
328        }
329
330        /**
331     * utility method to load classes
332     * @param className the name of the class to load
333     * @param errorMessage
334     *      Error message to use when the resolution fails.
335     * @return the class specified by <code>className</code>
336     */
337    private Class getClass(String className, Localizable errorMessage) {
338        try {
339            if (classLoader == null)
340                return Thread.currentThread().getContextClassLoader().loadClass(className);
341            else
342                return classLoader.loadClass(className);
343        } catch (ClassNotFoundException e) {
344            throw new RuntimeModelerException(errorMessage);
345        }
346    }
347
348    private boolean noWrapperGen() {
349        Object o = config.properties().get(SuppressDocLitWrapperGeneration);
350        return (o!= null && o instanceof Boolean) ? ((Boolean) o) : false;
351    }
352
353    private Class getRequestWrapperClass(String className, Method method, QName reqElemName) {
354        ClassLoader loader =  (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader;
355        try {
356            return loader.loadClass(className);
357        } catch (ClassNotFoundException e) {
358            if (noWrapperGen()) return WrapperComposite.class;
359            logger.fine("Dynamically creating request wrapper Class " + className);
360            return WrapperBeanGenerator.createRequestWrapperBean(className, method, reqElemName, loader);
361        }
362    }
363
364    private Class getResponseWrapperClass(String className, Method method, QName resElemName) {
365        ClassLoader loader =  (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader;
366        try {
367            return loader.loadClass(className);
368        } catch (ClassNotFoundException e) {
369            if (noWrapperGen()) return WrapperComposite.class;
370            logger.fine("Dynamically creating response wrapper bean Class " + className);
371            return WrapperBeanGenerator.createResponseWrapperBean(className, method, resElemName, loader);
372        }
373    }
374
375
376    private Class getExceptionBeanClass(String className, Class exception, String name, String namespace) {
377        boolean decapitalizeExceptionBeanProperties = true;
378        Object o = config.properties().get(DecapitalizeExceptionBeanProperties);
379        if (o!= null && o instanceof Boolean) decapitalizeExceptionBeanProperties = (Boolean) o;
380        ClassLoader loader =  (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader;
381        try {
382            return loader.loadClass(className);
383        } catch (ClassNotFoundException e) {
384            if (noWrapperGen()) return exception;
385            logger.fine("Dynamically creating exception bean Class " + className);
386            return WrapperBeanGenerator.createExceptionBean(className, exception, targetNamespace, name, namespace, loader, decapitalizeExceptionBeanProperties);
387        }
388    }
389
390    protected void determineWebMethodUse(Class clazz) {
391        if (clazz == null)
392            return;
393        if (!clazz.isInterface()) {
394            if (clazz == Object.class)
395                return;
396            WebMethod webMethod;
397            for (Method method : clazz.getMethods()) {
398                if (method.getDeclaringClass()!=clazz)
399                    continue;
400                webMethod = getAnnotation(method, WebMethod.class);
401                if (webMethod != null && !webMethod.exclude()) {
402                    classUsesWebMethod.add(clazz);
403                    break;
404                }
405            }
406        }
407        determineWebMethodUse(clazz.getSuperclass());
408    }
409
410    void processClass(Class clazz) {
411        classUsesWebMethod = new HashSet<Class>();
412        determineWebMethodUse(clazz);
413        WebService webService = getAnnotation(clazz, WebService.class);
414        QName portTypeName = getPortTypeName(clazz, targetNamespace, metadataReader);
415//        String portTypeLocalName  = clazz.getSimpleName();
416//        if (webService.name().length() >0)
417//            portTypeLocalName = webService.name();
418//
419//        targetNamespace = webService.targetNamespace();
420        packageName = "";
421        if (clazz.getPackage() != null)
422            packageName = clazz.getPackage().getName();
423//        if (targetNamespace.length() == 0) {
424//            targetNamespace = getNamespace(packageName);
425//        }
426//        model.setTargetNamespace(targetNamespace);
427//        QName portTypeName = new QName(targetNamespace, portTypeLocalName);
428        targetNamespace = portTypeName.getNamespaceURI();
429        model.setPortTypeName(portTypeName);
430        model.setTargetNamespace(targetNamespace);
431        model.defaultSchemaNamespaceSuffix = config.getMappingInfo().getDefaultSchemaNamespaceSuffix();
432        model.setWSDLLocation(webService.wsdlLocation());
433
434        SOAPBinding soapBinding = getAnnotation(clazz, SOAPBinding.class);
435        if (soapBinding != null) {
436            if (soapBinding.style() == SOAPBinding.Style.RPC && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
437                throw new RuntimeModelerException("runtime.modeler.invalid.soapbinding.parameterstyle",
438                        soapBinding, clazz);
439
440            }
441            isWrapped = soapBinding.parameterStyle()== WRAPPED;
442        }
443        defaultBinding = createBinding(soapBinding);
444        /*
445         * if clazz != portClass then there is an SEI.  If there is an
446         * SEI, then all methods should be processed.  However, if there is
447         * no SEI, and the implementation class uses at least one
448         * WebMethod annotation, then only methods with this annotation
449         * will be processed.
450         */
451/*        if (clazz == portClass) {
452            WebMethod webMethod;
453            for (Method method : clazz.getMethods()) {
454                webMethod = getPrivMethodAnnotation(method, WebMethod.class);
455                if (webMethod != null &&
456                    !webMethod.exclude()) {
457                    usesWebMethod = true;
458                    break;
459                }
460            }
461        }*/
462
463        for (Method method : clazz.getMethods()) {
464            if (!clazz.isInterface()) {     // if clazz is SEI, then all methods are web methods
465                if (method.getDeclaringClass() == Object.class) continue;
466                if (!getBooleanSystemProperty("com.sun.xml.internal.ws.legacyWebMethod")) {  // legacy webMethod computation behaviour to be used
467                    if (!isWebMethodBySpec(method, clazz))
468                        continue;
469                } else {
470                    if (!isWebMethod(method))
471                        continue;
472                }
473            }
474            // TODO: binding can be null. We need to figure out how to post-process
475            // RuntimeModel to link to WSDLModel
476            processMethod(method);
477        }
478        //Add additional jaxb classes referenced by {@link XmlSeeAlso}
479        XmlSeeAlso xmlSeeAlso = getAnnotation(clazz, XmlSeeAlso.class);
480        if(xmlSeeAlso != null)
481            model.addAdditionalClasses(xmlSeeAlso.value());
482    }
483
484    /*
485     * Section 3.3 of spec
486     * Otherwise, the class implicitly defines a service endpoint interface (SEI) which
487     * comprises all of the public methods that satisfy one of the following conditions:
488     *  1. They are annotated with the javax.jws.WebMethod annotation with the exclude element set to
489     *     false or missing (since false is the default for this annotation element).
490     *  2. They are not annotated with the javax.jws.WebMethod annotation but their declaring class has a
491     *     javax.jws.WebService annotation.
492     *
493     * also the method should non-static or non-final
494     */
495    private boolean isWebMethodBySpec(Method method, Class clazz) {
496
497        int modifiers = method.getModifiers();
498        boolean staticFinal = Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers);
499
500        assert Modifier.isPublic(modifiers);
501        assert !clazz.isInterface();
502
503        WebMethod webMethod = getAnnotation(method, WebMethod.class);
504        if (webMethod != null) {
505            if (webMethod.exclude()) {
506                return false;       // @WebMethod(exclude="true")
507            }
508            if (staticFinal) {
509                throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATICFINAL(method));
510            }
511            return true;            // @WebMethod
512        }
513
514        if (staticFinal) {
515            return false;
516        }
517
518        Class declClass = method.getDeclaringClass();
519        return getAnnotation(declClass, WebService.class) != null;
520    }
521
522    private boolean isWebMethod(Method method) {
523        int modifiers = method.getModifiers();
524        if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers))
525            return false;
526
527        Class clazz = method.getDeclaringClass();
528        boolean declHasWebService = getAnnotation(clazz, WebService.class) != null;
529        WebMethod webMethod = getAnnotation(method, WebMethod.class);
530        if (webMethod != null && !webMethod.exclude() && declHasWebService)
531            return true;
532        return declHasWebService && !classUsesWebMethod.contains(clazz);
533    }
534
535    /**
536     * creates a runtime model <code>SOAPBinding</code> from a <code>javax.jws.soap.SOAPBinding</code> object
537     * @param soapBinding the <code>javax.jws.soap.SOAPBinding</code> to model
538     * @return returns the runtime model SOAPBinding corresponding to <code>soapBinding</code>
539     */
540    protected SOAPBindingImpl createBinding(SOAPBinding soapBinding) {
541        SOAPBindingImpl rtSOAPBinding = new SOAPBindingImpl();
542        Style style = soapBinding!=null ? soapBinding.style() : Style.DOCUMENT;
543        rtSOAPBinding.setStyle(style);
544        assert bindingId != null;
545        model.bindingId = bindingId;
546        SOAPVersion soapVersion = bindingId.getSOAPVersion();
547        rtSOAPBinding.setSOAPVersion(soapVersion);
548        return rtSOAPBinding;
549    }
550
551    /**
552     * gets the namespace <code>String</code> for a given <code>packageName</code>
553     * @param packageName the name of the package used to find a namespace.
554     *      can be empty.
555     * @return the namespace for the specified <code>packageName</code>
556     */
557    public static String getNamespace(@NotNull String packageName) {
558        if (packageName.length() == 0)
559            return null;
560
561        StringTokenizer tokenizer = new StringTokenizer(packageName, ".");
562        String[] tokens;
563        if (tokenizer.countTokens() == 0) {
564            tokens = new String[0];
565        } else {
566            tokens = new String[tokenizer.countTokens()];
567            for (int i=tokenizer.countTokens()-1; i >= 0; i--) {
568                tokens[i] = tokenizer.nextToken();
569            }
570        }
571        StringBuilder namespace = new StringBuilder("http://");
572        for (int i=0; i<tokens.length; i++) {
573            if (i!=0)
574                namespace.append('.');
575            namespace.append(tokens[i]);
576        }
577        namespace.append('/');
578        return namespace.toString();
579    }
580
581    /*
582     * Returns true if an exception is service specific exception as per JAX-WS rules.
583     * @param exception
584     * @return
585     */
586    private boolean isServiceException(Class<?> exception) {
587        return EXCEPTION_CLASS.isAssignableFrom(exception) &&
588                !(RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || isRemoteException(exception));
589    }
590
591    /**
592     * creates the runtime model for a method on the <code>portClass</code>
593     * @param method the method to model
594     */
595    private void processMethod(Method method) {
596//        int mods = method.getModifiers();
597        WebMethod webMethod = getAnnotation(method, WebMethod.class);
598        if (webMethod != null && webMethod.exclude()) return;
599/*
600        validations are already done
601
602        if (!Modifier.isPublic(mods) || Modifier.isStatic(mods)) {
603            if(webMethod != null) {
604                // if the user put @WebMethod on these non-qualifying method,
605                // it's an error
606                if(Modifier.isStatic(mods))
607                    throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATIC(method));
608                else
609                    throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_PUBLIC(method));
610            }
611            return;
612        }
613
614        if (webMethod != null && webMethod.exclude())
615            return;
616*/
617
618        String methodName = method.getName();
619        boolean isOneway = (getAnnotation(method, Oneway.class) != null);
620
621        //Check that oneway methods don't thorw any checked exceptions
622        if (isOneway) {
623            for (Class<?> exception : method.getExceptionTypes()) {
624                if(isServiceException(exception)) {
625                       throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.checked.exceptions",
626                            portClass.getCanonicalName(), methodName, exception.getName());
627                }
628            }
629        }
630
631        JavaMethodImpl javaMethod;
632        //Class implementorClass = portClass;
633        if (method.getDeclaringClass()==portClass) {
634            javaMethod = new JavaMethodImpl(model,method,method,metadataReader);
635        } else {
636            try {
637                Method tmpMethod = portClass.getMethod(method.getName(),
638                    method.getParameterTypes());
639                javaMethod = new JavaMethodImpl(model,tmpMethod,method,metadataReader);
640            } catch (NoSuchMethodException e) {
641                throw new RuntimeModelerException("runtime.modeler.method.not.found",
642                    method.getName(), portClass.getName());
643            }
644        }
645
646
647
648        //set MEP -oneway, async, req/resp
649        MEP mep = getMEP(method);
650        javaMethod.setMEP(mep);
651
652        String action = null;
653
654
655        String operationName = method.getName();
656        if (webMethod != null ) {
657            action = webMethod.action();
658            operationName = webMethod.operationName().length() > 0 ?
659                webMethod.operationName() :
660                operationName;
661        }
662
663        //override the @WebMethod.action value by the one from the WSDL
664        if(binding != null){
665            WSDLBoundOperation bo = binding.getBinding().get(new QName(targetNamespace, operationName));
666            if(bo != null){
667                WSDLInput wsdlInput = bo.getOperation().getInput();
668                String wsaAction = wsdlInput.getAction();
669                if(wsaAction != null && !wsdlInput.isDefaultAction())
670                    action = wsaAction;
671                else
672                    action = bo.getSOAPAction();
673            }
674        }
675
676        javaMethod.setOperationQName(new QName(targetNamespace,operationName));
677        SOAPBinding methodBinding = getAnnotation(method, SOAPBinding.class);
678        if(methodBinding != null && methodBinding.style() == SOAPBinding.Style.RPC) {
679            logger.warning(ModelerMessages.RUNTIMEMODELER_INVALID_SOAPBINDING_ON_METHOD(methodBinding, method.getName(), method.getDeclaringClass().getName()));
680        } else if (methodBinding == null && !method.getDeclaringClass().equals(portClass)) {
681            methodBinding = getAnnotation(method.getDeclaringClass(), SOAPBinding.class);
682            if (methodBinding != null && methodBinding.style() == SOAPBinding.Style.RPC && methodBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
683                throw new RuntimeModelerException("runtime.modeler.invalid.soapbinding.parameterstyle",
684                        methodBinding, method.getDeclaringClass());
685            }
686        }
687
688        if(methodBinding!= null && defaultBinding.getStyle() != methodBinding.style()) {
689             throw new RuntimeModelerException("runtime.modeler.soapbinding.conflict",
690                    methodBinding.style(), method.getName(),defaultBinding.getStyle());
691        }
692
693        boolean methodIsWrapped = isWrapped;
694        Style style = defaultBinding.getStyle();
695        if (methodBinding != null) {
696            SOAPBindingImpl mySOAPBinding = createBinding(methodBinding);
697            style = mySOAPBinding.getStyle();
698            if (action != null)
699                mySOAPBinding.setSOAPAction(action);
700            methodIsWrapped = methodBinding.parameterStyle().equals(
701                WRAPPED);
702            javaMethod.setBinding(mySOAPBinding);
703        } else {
704            SOAPBindingImpl sb = new SOAPBindingImpl(defaultBinding);
705            if (action != null) {
706                sb.setSOAPAction(action);
707            } else {
708                String defaults = SOAPVersion.SOAP_11 == sb.getSOAPVersion() ? "" : null;
709                sb.setSOAPAction(defaults);
710            }
711            javaMethod.setBinding(sb);
712        }
713        if (!methodIsWrapped) {
714            processDocBareMethod(javaMethod, operationName, method);
715        } else if (style.equals(Style.DOCUMENT)) {
716            processDocWrappedMethod(javaMethod, methodName, operationName,
717                method);
718        } else {
719            processRpcMethod(javaMethod, methodName, operationName, method);
720        }
721        model.addJavaMethod(javaMethod);
722    }
723
724    private MEP getMEP(Method m){
725        if (getAnnotation(m, Oneway.class)!= null) {
726            return MEP.ONE_WAY;
727        }
728        if(Response.class.isAssignableFrom(m.getReturnType())){
729            return MEP.ASYNC_POLL;
730        }else if(Future.class.isAssignableFrom(m.getReturnType())){
731            return MEP.ASYNC_CALLBACK;
732        }
733        return MEP.REQUEST_RESPONSE;
734    }
735
736    /**
737     * models a document/literal wrapped method
738     * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
739     * @param methodName the runtime model <code>JavaMethod</code> instance being created
740     * @param operationName the runtime model <code>JavaMethod</code> instance being created
741     * @param method the <code>method</code> to model
742     */
743    protected void processDocWrappedMethod(JavaMethodImpl javaMethod, String methodName,
744                                           String operationName, Method method) {
745        boolean methodHasHeaderParams = false;
746        boolean isOneway = getAnnotation(method, Oneway.class)!= null;
747        RequestWrapper reqWrapper = getAnnotation(method,RequestWrapper.class);
748        ResponseWrapper resWrapper = getAnnotation(method,ResponseWrapper.class);
749        String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
750        if (packageName == null || packageName.length() == 0) {
751            beanPackage = JAXWS_PACKAGE_PD;
752        }
753        String requestClassName;
754        if(reqWrapper != null && reqWrapper.className().length()>0){
755            requestClassName = reqWrapper.className();
756        }else{
757            requestClassName = beanPackage + capitalize(method.getName());
758        }
759
760
761        String responseClassName;
762        if(resWrapper != null && resWrapper.className().length()>0){
763            responseClassName = resWrapper.className();
764        }else{
765            responseClassName = beanPackage + capitalize(method.getName()) + RESPONSE;
766        }
767
768        String reqName = operationName;
769        String reqNamespace = targetNamespace;
770        String reqPartName = "parameters";
771        if (reqWrapper != null) {
772            if (reqWrapper.targetNamespace().length() > 0)
773                reqNamespace = reqWrapper.targetNamespace();
774            if (reqWrapper.localName().length() > 0)
775                reqName = reqWrapper.localName();
776            try {
777                if (reqWrapper.partName().length() > 0)
778                    reqPartName = reqWrapper.partName();
779            } catch(LinkageError e) {
780                //2.1 API dopes n't have this method
781                //Do nothing, just default to "parameters"
782            }
783        }
784        QName reqElementName = new QName(reqNamespace, reqName);
785        javaMethod.setRequestPayloadName(reqElementName);
786        Class requestClass = getRequestWrapperClass(requestClassName, method, reqElementName);
787
788        Class responseClass = null;
789        String resName = operationName+"Response";
790        String resNamespace = targetNamespace;
791        QName resElementName = null;
792        String resPartName = "parameters";
793        if (!isOneway) {
794            if (resWrapper != null) {
795                if (resWrapper.targetNamespace().length() > 0)
796                    resNamespace = resWrapper.targetNamespace();
797                if (resWrapper.localName().length() > 0)
798                    resName = resWrapper.localName();
799                try {
800                    if (resWrapper.partName().length() > 0)
801                        resPartName = resWrapper.partName();
802                } catch (LinkageError e) {
803                    //2.1 API does n't have this method
804                    //Do nothing, just default to "parameters"
805                }
806            }
807            resElementName = new QName(resNamespace, resName);
808            responseClass = getResponseWrapperClass(responseClassName, method, resElementName);
809        }
810
811        TypeInfo typeRef =
812                new TypeInfo(reqElementName, requestClass);
813        typeRef.setNillable(false);
814        WrapperParameter requestWrapper = new WrapperParameter(javaMethod, typeRef,
815            Mode.IN, 0);
816        requestWrapper.setPartName(reqPartName);
817        requestWrapper.setBinding(ParameterBinding.BODY);
818        javaMethod.addParameter(requestWrapper);
819        WrapperParameter responseWrapper = null;
820        if (!isOneway) {
821            typeRef = new TypeInfo(resElementName, responseClass);
822            typeRef.setNillable(false);
823            responseWrapper = new WrapperParameter(javaMethod, typeRef, Mode.OUT, -1);
824            javaMethod.addParameter(responseWrapper);
825            responseWrapper.setBinding(ParameterBinding.BODY);
826        }
827
828        // return value
829
830
831        WebResult webResult = getAnnotation(method, WebResult.class);
832        XmlElement xmlElem = getAnnotation(method, XmlElement.class);
833        QName resultQName = getReturnQName(method, webResult, xmlElem);
834        Class returnType = method.getReturnType();
835        boolean isResultHeader = false;
836        if (webResult != null) {
837            isResultHeader = webResult.header();
838            methodHasHeaderParams = isResultHeader || methodHasHeaderParams;
839            if (isResultHeader && xmlElem != null) {
840                throw new RuntimeModelerException("@XmlElement cannot be specified on method "+method+" as the return value is bound to header");
841            }
842            if (resultQName.getNamespaceURI().length() == 0 && webResult.header()) {
843                // headers must have a namespace
844                resultQName = new QName(targetNamespace, resultQName.getLocalPart());
845            }
846        }
847
848        if(javaMethod.isAsync()){
849            returnType = getAsyncReturnType(method, returnType);
850            resultQName = new QName(RETURN);
851        }
852        resultQName = qualifyWrappeeIfNeeded(resultQName, resNamespace);
853        if (!isOneway && (returnType != null) && (!returnType.getName().equals("void"))) {
854            Annotation[] rann = getAnnotations(method);
855            if (resultQName.getLocalPart() != null) {
856                TypeInfo rTypeReference = new TypeInfo(resultQName, returnType, rann);
857                metadataReader.getProperties(rTypeReference.properties(), method);
858                rTypeReference.setGenericType(method.getGenericReturnType());
859                ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1);
860                if (isResultHeader) {
861                    returnParameter.setBinding(ParameterBinding.HEADER);
862                    javaMethod.addParameter(returnParameter);
863                } else {
864                    returnParameter.setBinding(ParameterBinding.BODY);
865                    responseWrapper.addWrapperChild(returnParameter);
866                }
867            }
868        }
869
870        //get WebParam
871        Class<?>[] parameterTypes = method.getParameterTypes();
872        Type[] genericParameterTypes = method.getGenericParameterTypes();
873        Annotation[][] pannotations = getParamAnnotations(method);
874        int pos = 0;
875        for (Class clazzType : parameterTypes) {
876            String partName=null;
877            String paramName = "arg"+pos;
878            //String paramNamespace = "";
879            boolean isHeader = false;
880
881            if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
882                continue;
883            }
884
885            boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
886            //set the actual type argument of Holder in the TypeReference
887            if (isHolder) {
888                if(clazzType==Holder.class){
889                    clazzType = erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]);
890                }
891            }
892            Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
893            WebParam webParam = null;
894            xmlElem = null;
895            for (Annotation annotation : pannotations[pos]) {
896                if (annotation.annotationType() == WebParam.class)
897                    webParam = (WebParam)annotation;
898                else if (annotation.annotationType() == XmlElement.class)
899                    xmlElem = (XmlElement)annotation;
900            }
901
902            QName paramQName = getParameterQName(method, webParam, xmlElem, paramName);
903            if (webParam != null) {
904                isHeader = webParam.header();
905                methodHasHeaderParams = isHeader || methodHasHeaderParams;
906                if (isHeader && xmlElem != null) {
907                    throw new RuntimeModelerException("@XmlElement cannot be specified on method "+method+" parameter that is bound to header");
908                }
909                if(webParam.partName().length() > 0)
910                    partName = webParam.partName();
911                else
912                    partName = paramQName.getLocalPart();
913                if (isHeader && paramQName.getNamespaceURI().equals("")) { // headers cannot be in empty namespace
914                    paramQName = new QName(targetNamespace, paramQName.getLocalPart());
915                }
916                paramMode = webParam.mode();
917                if (isHolder && paramMode == Mode.IN)
918                    paramMode = Mode.INOUT;
919            }
920            paramQName = qualifyWrappeeIfNeeded(paramQName, reqNamespace);
921            typeRef =
922                new TypeInfo(paramQName, clazzType, pannotations[pos]);
923            metadataReader.getProperties(typeRef.properties(), method, pos);
924            typeRef.setGenericType(genericParameterTypes[pos]);
925            ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++);
926
927            if (isHeader) {
928                param.setBinding(ParameterBinding.HEADER);
929                javaMethod.addParameter(param);
930                param.setPartName(partName);
931            } else {
932                param.setBinding(ParameterBinding.BODY);
933                if (paramMode!=Mode.OUT) {
934                    requestWrapper.addWrapperChild(param);
935                }
936                if (paramMode!=Mode.IN) {
937                    if (isOneway) {
938                        throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.out.parameters",
939                            portClass.getCanonicalName(), methodName);
940                    }
941                    responseWrapper.addWrapperChild(param);
942                }
943            }
944        }
945
946        //If the method has any parameter or return type that is bound to a header, use "result" as part name to avoid
947        // name collison of same input part name and output part name ("parameters") shown up as param names on the
948        // client mapping.
949        if(methodHasHeaderParams) {
950            resPartName = "result";
951        }
952        if(responseWrapper != null)
953            responseWrapper.setPartName(resPartName);
954        processExceptions(javaMethod, method);
955    }
956
957    private QName qualifyWrappeeIfNeeded(QName resultQName, String ns) {
958        Object o = config.properties().get(DocWrappeeNamespapceQualified);
959        boolean qualified = (o!= null && o instanceof Boolean) ? ((Boolean) o) : false;
960        if (qualified) {
961            if (resultQName.getNamespaceURI() == null || "".equals(resultQName.getNamespaceURI())) {
962                return new QName(ns, resultQName.getLocalPart());
963            }
964        }
965        return resultQName;
966    }
967
968    /**
969     * models a rpc/literal method
970     * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
971     * @param methodName the name of the <code>method</code> being modeled.
972     * @param operationName the WSDL operation name for this <code>method</code>
973     * @param method the runtime model <code>JavaMethod</code> instance being created
974     */
975    protected void processRpcMethod(JavaMethodImpl javaMethod, String methodName,
976                                    String operationName, Method method) {
977        boolean isOneway = getAnnotation(method, Oneway.class) != null;
978
979        // use Map to build parameters in the part order when they are known.
980        // if part is unbound, we just put them at the end, and for that we
981        // use a large index (10000+) to avoid colliding with ordered ones.
982        // this assumes that there's no operation with # of parameters > 10000,
983        // but I think it's a pretty safe assumption - KK.
984        Map<Integer, ParameterImpl> resRpcParams = new TreeMap<Integer, ParameterImpl>();
985        Map<Integer, ParameterImpl> reqRpcParams = new TreeMap<Integer, ParameterImpl>();
986
987        //Lets take the service namespace and overwrite it with the one we get it from wsdl
988        String reqNamespace = targetNamespace;
989        String respNamespace = targetNamespace;
990
991        if(binding != null && Style.RPC.equals(binding.getBinding().getStyle())){
992            QName opQName = new QName(binding.getBinding().getPortTypeName().getNamespaceURI(), operationName);
993            WSDLBoundOperation op = binding.getBinding().get(opQName);
994            if(op != null){
995                //it cant be null, but lets not fail and try to work with service namespce
996                if(op.getRequestNamespace() != null){
997                    reqNamespace = op.getRequestNamespace();
998                }
999
1000                //it cant be null, but lets not fail and try to work with service namespce
1001                if(op.getResponseNamespace() != null){
1002                    respNamespace = op.getResponseNamespace();
1003                }
1004            }
1005        }
1006
1007        QName reqElementName = new QName(reqNamespace, operationName);
1008        javaMethod.setRequestPayloadName(reqElementName);
1009        QName resElementName = null;
1010        if (!isOneway) {
1011            resElementName = new QName(respNamespace, operationName+RESPONSE);
1012        }
1013
1014        Class wrapperType = WrapperComposite.class;
1015        TypeInfo typeRef = new TypeInfo(reqElementName, wrapperType);
1016        WrapperParameter requestWrapper = new WrapperParameter(javaMethod, typeRef, Mode.IN, 0);
1017        requestWrapper.setInBinding(ParameterBinding.BODY);
1018        javaMethod.addParameter(requestWrapper);
1019        WrapperParameter responseWrapper = null;
1020        if (!isOneway) {
1021            typeRef = new TypeInfo(resElementName, wrapperType);
1022            responseWrapper = new WrapperParameter(javaMethod, typeRef, Mode.OUT, -1);
1023            responseWrapper.setOutBinding(ParameterBinding.BODY);
1024            javaMethod.addParameter(responseWrapper);
1025        }
1026
1027        Class returnType = method.getReturnType();
1028        String resultName = RETURN;
1029        String resultTNS = targetNamespace;
1030        String resultPartName = resultName;
1031        boolean isResultHeader = false;
1032        WebResult webResult = getAnnotation(method, WebResult.class);
1033
1034        if (webResult != null) {
1035            isResultHeader = webResult.header();
1036            if (webResult.name().length() > 0)
1037                resultName = webResult.name();
1038            if (webResult.partName().length() > 0) {
1039                resultPartName = webResult.partName();
1040                if (!isResultHeader)
1041                    resultName = resultPartName;
1042            } else
1043                resultPartName = resultName;
1044            if (webResult.targetNamespace().length() > 0)
1045                resultTNS = webResult.targetNamespace();
1046            isResultHeader = webResult.header();
1047        }
1048        QName resultQName;
1049        if (isResultHeader)
1050            resultQName = new QName(resultTNS, resultName);
1051        else
1052            resultQName = new QName(resultName);
1053
1054        if(javaMethod.isAsync()){
1055            returnType = getAsyncReturnType(method, returnType);
1056        }
1057
1058        if (!isOneway && returnType!=null && returnType!=void.class) {
1059            Annotation[] rann = getAnnotations(method);
1060            TypeInfo rTypeReference = new TypeInfo(resultQName, returnType, rann);
1061            metadataReader.getProperties(rTypeReference.properties(), method);
1062            rTypeReference.setGenericType(method.getGenericReturnType());
1063            ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1);
1064            returnParameter.setPartName(resultPartName);
1065            if(isResultHeader){
1066                returnParameter.setBinding(ParameterBinding.HEADER);
1067                javaMethod.addParameter(returnParameter);
1068                rTypeReference.setGlobalElement(true);
1069            }else{
1070                ParameterBinding rb = getBinding(operationName, resultPartName, false, Mode.OUT);
1071                returnParameter.setBinding(rb);
1072                if(rb.isBody()){
1073                    rTypeReference.setGlobalElement(false);
1074                    WSDLPart p = getPart(new QName(targetNamespace,operationName), resultPartName, Mode.OUT);
1075                    if(p == null)
1076                        resRpcParams.put(resRpcParams.size()+10000, returnParameter);
1077                    else
1078                        resRpcParams.put(p.getIndex(), returnParameter);
1079                }else{
1080                    javaMethod.addParameter(returnParameter);
1081                }
1082            }
1083        }
1084
1085        //get WebParam
1086        Class<?>[] parameterTypes = method.getParameterTypes();
1087        Type[] genericParameterTypes = method.getGenericParameterTypes();
1088        Annotation[][] pannotations = getParamAnnotations(method);
1089        int pos = 0;
1090        for (Class clazzType : parameterTypes) {
1091            String paramName = "";
1092            String paramNamespace = "";
1093            String partName = "";
1094            boolean isHeader = false;
1095
1096            if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
1097                continue;
1098            }
1099
1100            boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
1101            //set the actual type argument of Holder in the TypeReference
1102            if (isHolder) {
1103                if (clazzType==Holder.class)
1104                    clazzType = erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]);
1105            }
1106            Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
1107            for (Annotation annotation : pannotations[pos]) {
1108                if (annotation.annotationType() == javax.jws.WebParam.class) {
1109                    javax.jws.WebParam webParam = (javax.jws.WebParam) annotation;
1110                    paramName = webParam.name();
1111                    partName = webParam.partName();
1112                    isHeader = webParam.header();
1113                    WebParam.Mode mode = webParam.mode();
1114                    paramNamespace = webParam.targetNamespace();
1115                    if (isHolder && mode == Mode.IN)
1116                        mode = Mode.INOUT;
1117                    paramMode = mode;
1118                    break;
1119                }
1120            }
1121
1122            if (paramName.length() == 0) {
1123                paramName = "arg"+pos;
1124            }
1125            if (partName.length() == 0) {
1126                partName = paramName;
1127            } else if (!isHeader) {
1128                paramName = partName;
1129            }
1130            if (partName.length() == 0) {
1131                partName = paramName;
1132            }
1133
1134            QName paramQName;
1135            if (!isHeader) {
1136                //its rpclit body param, set namespace to ""
1137                paramQName = new QName("", paramName);
1138            } else {
1139                if (paramNamespace.length() == 0)
1140                    paramNamespace = targetNamespace;
1141                paramQName = new QName(paramNamespace, paramName);
1142            }
1143            typeRef =
1144                new TypeInfo(paramQName, clazzType, pannotations[pos]);
1145            metadataReader.getProperties(typeRef.properties(), method, pos);
1146            typeRef.setGenericType(genericParameterTypes[pos]);
1147            ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++);
1148            param.setPartName(partName);
1149
1150            if(paramMode == Mode.INOUT){
1151                ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN);
1152                param.setInBinding(pb);
1153                pb = getBinding(operationName, partName, isHeader, Mode.OUT);
1154                param.setOutBinding(pb);
1155            }else{
1156                if (isHeader) {
1157                    typeRef.setGlobalElement(true);
1158                    param.setBinding(ParameterBinding.HEADER);
1159                } else {
1160                    ParameterBinding pb = getBinding(operationName, partName, false, paramMode);
1161                    param.setBinding(pb);
1162                }
1163            }
1164            if(param.getInBinding().isBody()){
1165                typeRef.setGlobalElement(false);
1166                if(!param.isOUT()){
1167                    WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.IN);
1168                    if(p == null)
1169                        reqRpcParams.put(reqRpcParams.size()+10000, param);
1170                    else
1171                        reqRpcParams.put(param.getIndex(), param);
1172                }
1173
1174                if(!param.isIN()){
1175                    if (isOneway) {
1176                            throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.out.parameters",
1177                                portClass.getCanonicalName(), methodName);
1178                    }
1179                    WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.OUT);
1180                    if(p == null)
1181                        resRpcParams.put(resRpcParams.size()+10000, param);
1182                    else
1183                        resRpcParams.put(p.getIndex(), param);
1184                }
1185            }else{
1186                javaMethod.addParameter(param);
1187            }
1188        }
1189        for (ParameterImpl p : reqRpcParams.values())
1190            requestWrapper.addWrapperChild(p);
1191        for (ParameterImpl p : resRpcParams.values())
1192            responseWrapper.addWrapperChild(p);
1193        processExceptions(javaMethod, method);
1194    }
1195
1196    /**
1197     * models the exceptions thrown by <code>method</code> and adds them to the <code>javaMethod</code>
1198     * runtime model object
1199     * @param javaMethod the runtime model object to add the exception model objects to
1200     * @param method the <code>method</code> from which to find the exceptions to model
1201     */
1202    protected void processExceptions(JavaMethodImpl javaMethod, Method method) {
1203        Action actionAnn = getAnnotation(method, Action.class);
1204        FaultAction[] faultActions = {};
1205        if(actionAnn != null)
1206            faultActions = actionAnn.fault();
1207        for (Class<?> exception : method.getExceptionTypes()) {
1208
1209            //Exclude RuntimeException, RemoteException and Error etc
1210            if (!EXCEPTION_CLASS.isAssignableFrom(exception))
1211                continue;
1212            if (RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || isRemoteException(exception))
1213                continue;
1214            if (getAnnotation(exception, javax.xml.bind.annotation.XmlTransient.class) != null)
1215                continue;
1216            Class exceptionBean;
1217            Annotation[] anns;
1218            WebFault webFault = getAnnotation(exception, WebFault.class);
1219            Method faultInfoMethod = getWSDLExceptionFaultInfo(exception);
1220            ExceptionType exceptionType = ExceptionType.WSDLException;
1221            String namespace = targetNamespace;
1222            String name = exception.getSimpleName();
1223            String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
1224            if (packageName.length() == 0)
1225                beanPackage = JAXWS_PACKAGE_PD;
1226            String className = beanPackage+ name + BEAN;
1227            String messageName = exception.getSimpleName();
1228            if (webFault != null) {
1229                if (webFault.faultBean().length()>0)
1230                    className = webFault.faultBean();
1231                if (webFault.name().length()>0)
1232                    name = webFault.name();
1233                if (webFault.targetNamespace().length()>0)
1234                    namespace = webFault.targetNamespace();
1235                if (webFault.messageName().length()>0)
1236                    messageName = webFault.messageName();
1237            }
1238            if (faultInfoMethod == null)  {
1239                exceptionBean = getExceptionBeanClass(className, exception, name, namespace);
1240                exceptionType = ExceptionType.UserDefined;
1241                anns = getAnnotations(exceptionBean);
1242            } else {
1243                exceptionBean = faultInfoMethod.getReturnType();
1244                anns = getAnnotations(faultInfoMethod);
1245            }
1246            QName faultName = new QName(namespace, name);
1247            TypeInfo typeRef = new TypeInfo(faultName, exceptionBean, anns);
1248            CheckedExceptionImpl checkedException =
1249                new CheckedExceptionImpl(javaMethod, exception, typeRef, exceptionType);
1250            checkedException.setMessageName(messageName);
1251            checkedException.setFaultInfoGetter(faultInfoMethod);
1252            for(FaultAction fa: faultActions) {
1253                if(fa.className().equals(exception) && !fa.value().equals("")) {
1254                    checkedException.setFaultAction(fa.value());
1255                    break;
1256                }
1257            }
1258            javaMethod.addException(checkedException);
1259        }
1260    }
1261
1262    /**
1263     * returns the method that corresponds to "getFaultInfo".  Returns null if this is not an
1264     * exception generated from a WSDL
1265     * @param exception the class to search for the "getFaultInfo" method
1266     * @return the method named "getFaultInfo" if this is an exception generated from WSDL or an
1267     * exception that contains the <code>WebFault</code> annotation.  Otherwise it returns null
1268     */
1269    protected Method getWSDLExceptionFaultInfo(Class exception) {
1270//      if (!exception.isAnnotationPresent(WebFault.class))
1271        if (getAnnotation(exception, WebFault.class) == null)
1272            return null;
1273        try {
1274            return exception.getMethod("getFaultInfo");
1275        } catch (NoSuchMethodException e) {
1276            return null;
1277        }
1278    }
1279
1280    /**
1281     * models a document/literal bare method
1282     * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
1283     * @param operationName the runtime model <code>JavaMethod</code> instance being created
1284     * @param method the runtime model <code>JavaMethod</code> instance being created
1285     */
1286    protected void processDocBareMethod(JavaMethodImpl javaMethod,
1287                                       String operationName, Method method) {
1288
1289        String resultName = operationName+RESPONSE;
1290        String resultTNS = targetNamespace;
1291        String resultPartName = null;
1292        boolean isResultHeader = false;
1293        WebResult webResult = getAnnotation(method, WebResult.class);
1294        if (webResult != null) {
1295            if (webResult.name().length() > 0)
1296                resultName = webResult.name();
1297            if (webResult.targetNamespace().length() > 0)
1298                resultTNS = webResult.targetNamespace();
1299            resultPartName = webResult.partName();
1300            isResultHeader = webResult.header();
1301        }
1302
1303        Class returnType = method.getReturnType();
1304        Type gReturnType = method.getGenericReturnType();
1305        if(javaMethod.isAsync()){
1306            returnType = getAsyncReturnType(method, returnType);
1307        }
1308
1309        if ((returnType != null) && (!returnType.getName().equals("void"))) {
1310            Annotation[] rann = getAnnotations(method);
1311            if (resultName != null) {
1312                QName responseQName = new QName(resultTNS, resultName);
1313                TypeInfo rTypeReference = new TypeInfo(responseQName, returnType, rann);
1314                rTypeReference.setGenericType(gReturnType);
1315                metadataReader.getProperties(rTypeReference.properties(), method);
1316                ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1);
1317
1318                if(resultPartName == null || (resultPartName.length() == 0)){
1319                    resultPartName = resultName;
1320                }
1321                returnParameter.setPartName(resultPartName);
1322                if(isResultHeader){
1323                    returnParameter.setBinding(ParameterBinding.HEADER);
1324                }else{
1325                    ParameterBinding rb = getBinding(operationName, resultPartName, false, Mode.OUT);
1326                    returnParameter.setBinding(rb);
1327                }
1328                javaMethod.addParameter(returnParameter);
1329            }
1330        }
1331
1332        //get WebParam
1333        Class<?>[] parameterTypes = method.getParameterTypes();
1334        Type[] genericParameterTypes = method.getGenericParameterTypes();
1335        Annotation[][] pannotations = getParamAnnotations(method);
1336        int pos = 0;
1337        for (Class clazzType : parameterTypes) {
1338            String paramName = operationName; //method.getName();
1339            String partName = null;
1340            String requestNamespace = targetNamespace;
1341            boolean isHeader = false;
1342
1343            //async
1344            if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
1345                continue;
1346            }
1347
1348            boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
1349            //set the actual type argument of Holder in the TypeReference
1350            if (isHolder) {
1351                if (clazzType==Holder.class)
1352                    clazzType = erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]);
1353            }
1354
1355            Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
1356            for (Annotation annotation : pannotations[pos]) {
1357                if (annotation.annotationType() == javax.jws.WebParam.class) {
1358                    javax.jws.WebParam webParam = (javax.jws.WebParam) annotation;
1359                    paramMode = webParam.mode();
1360                    if (isHolder && paramMode == Mode.IN)
1361                        paramMode = Mode.INOUT;
1362                    isHeader = webParam.header();
1363                    if(isHeader)
1364                        paramName = "arg"+pos;
1365                    if(paramMode == Mode.OUT && !isHeader)
1366                        paramName = operationName+RESPONSE;
1367                    if (webParam.name().length() > 0)
1368                        paramName = webParam.name();
1369                    partName = webParam.partName();
1370                    if (!webParam.targetNamespace().equals("")) {
1371                        requestNamespace = webParam.targetNamespace();
1372                    }
1373                    break;
1374                }
1375            }
1376
1377            QName requestQName = new QName(requestNamespace, paramName);
1378            if (!isHeader && paramMode != Mode.OUT) javaMethod.setRequestPayloadName(requestQName);
1379            //doclit/wrapped
1380            TypeInfo typeRef = //operationName with upper 1 char
1381                new TypeInfo(requestQName, clazzType,
1382                    pannotations[pos]);
1383            metadataReader.getProperties(typeRef.properties(), method, pos);
1384            typeRef.setGenericType(genericParameterTypes[pos]);
1385            ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++);
1386            if(partName == null || (partName.length() == 0)){
1387                partName = paramName;
1388            }
1389            param.setPartName(partName);
1390            if(paramMode == Mode.INOUT){
1391                ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN);
1392                param.setInBinding(pb);
1393                pb = getBinding(operationName, partName, isHeader, Mode.OUT);
1394                param.setOutBinding(pb);
1395            }else{
1396                if (isHeader){
1397                    param.setBinding(ParameterBinding.HEADER);
1398                }else{
1399                    ParameterBinding pb = getBinding(operationName, partName, false, paramMode);
1400                    param.setBinding(pb);
1401                }
1402            }
1403            javaMethod.addParameter(param);
1404        }
1405        validateDocBare(javaMethod);
1406        processExceptions(javaMethod, method);
1407    }
1408
1409    // Does a conservative check if there is only one BODY part for input
1410    // and output message. We are not considering INOUT parameters at this
1411    // time since binding information is not applied. Also, there isn't
1412    // anyway to represent some cases in SEI. For example, a INOUT parameter
1413    // could be bound to body for input message, header for OUTPUT message
1414    // in wsdl:binding
1415    private void validateDocBare(JavaMethodImpl javaMethod) {
1416        int numInBodyBindings = 0;
1417        for(Parameter param : javaMethod.getRequestParameters()){
1418            if(param.getBinding().equals(ParameterBinding.BODY) && param.isIN()){
1419                numInBodyBindings++;
1420            }
1421            if(numInBodyBindings > 1){
1422                throw new RuntimeModelerException(ModelerMessages.localizableNOT_A_VALID_BARE_METHOD(portClass.getName(), javaMethod.getMethod().getName()));
1423            }
1424        }
1425
1426        int numOutBodyBindings = 0;
1427        for(Parameter param : javaMethod.getResponseParameters()){
1428            if(param.getBinding().equals(ParameterBinding.BODY) && param.isOUT()){
1429                numOutBodyBindings++;
1430            }
1431            if(numOutBodyBindings > 1){
1432                throw new RuntimeModelerException(ModelerMessages.localizableNOT_A_VALID_BARE_METHOD(portClass.getName(), javaMethod.getMethod().getName()));
1433            }
1434        }
1435    }
1436
1437    private Class getAsyncReturnType(Method method, Class returnType) {
1438        if(Response.class.isAssignableFrom(returnType)){
1439            Type ret = method.getGenericReturnType();
1440            return erasure(((ParameterizedType)ret).getActualTypeArguments()[0]);
1441        }else{
1442            Type[] types = method.getGenericParameterTypes();
1443            Class[] params = method.getParameterTypes();
1444            int i = 0;
1445            for(Class cls : params){
1446                if(AsyncHandler.class.isAssignableFrom(cls)){
1447                    return erasure(((ParameterizedType)types[i]).getActualTypeArguments()[0]);
1448                }
1449                i++;
1450            }
1451        }
1452        return returnType;
1453    }
1454
1455    /**
1456     * utility to capitalize the first letter in a string
1457     * @param name the string to capitalize
1458     * @return the capitalized string
1459     */
1460    public static String capitalize(String name) {
1461        if (name == null || name.length() == 0) {
1462            return name;
1463        }
1464        char chars[] = name.toCharArray();
1465        chars[0] = Character.toUpperCase(chars[0]);
1466        return new String(chars);
1467    }
1468
1469    /*
1470    * Return service QName
1471    */
1472    /**
1473     * gets the <code>wsdl:serviceName</code> for a given implementation class
1474     * @param implClass the implementation class
1475     * @return the <code>wsdl:serviceName</code> for the <code>implClass</code>
1476     */
1477    public static QName getServiceName(Class<?> implClass) {
1478        return getServiceName(implClass, null);
1479    }
1480
1481    public static QName getServiceName(Class<?> implClass, boolean isStandard) {
1482        return getServiceName(implClass, null, isStandard);
1483    }
1484
1485    public static QName getServiceName(Class<?> implClass, MetadataReader reader) {
1486        return getServiceName(implClass, reader, true);
1487    }
1488
1489    public static QName getServiceName(Class<?> implClass, MetadataReader reader, boolean isStandard) {
1490        if (implClass.isInterface()) {
1491            throw new RuntimeModelerException("runtime.modeler.cannot.get.serviceName.from.interface",
1492                                    implClass.getCanonicalName());
1493        }
1494
1495        String name = implClass.getSimpleName()+SERVICE;
1496        String packageName = "";
1497        if (implClass.getPackage() != null)
1498            packageName = implClass.getPackage().getName();
1499
1500        WebService webService = getAnnotation(WebService.class, implClass, reader);
1501        if (isStandard && webService == null) {
1502            throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1503                implClass.getCanonicalName());
1504        }
1505        if (webService != null && webService.serviceName().length() > 0) {
1506            name = webService.serviceName();
1507        }
1508        String targetNamespace = getNamespace(packageName);
1509        if (webService != null && webService.targetNamespace().length() > 0) {
1510            targetNamespace = webService.targetNamespace();
1511        } else if (targetNamespace == null) {
1512            throw new RuntimeModelerException("runtime.modeler.no.package",
1513                implClass.getName());
1514        }
1515        return new QName(targetNamespace, name);
1516    }
1517
1518    /**
1519     * gets the <code>wsdl:portName</code> for a given implementation class
1520     * @param implClass the implementation class
1521     * @param targetNamespace Namespace URI for service name
1522     * @return the <code>wsdl:portName</code> for the <code>implClass</code>
1523     */
1524    public static QName getPortName(Class<?> implClass, String targetNamespace) {
1525        return getPortName(implClass, null, targetNamespace);
1526    }
1527
1528    public static QName getPortName(Class<?> implClass, String targetNamespace, boolean isStandard) {
1529        return getPortName(implClass, null, targetNamespace, isStandard);
1530    }
1531
1532    public static QName getPortName(Class<?> implClass, MetadataReader reader, String targetNamespace) {
1533        return getPortName(implClass, reader, targetNamespace, true);
1534    }
1535
1536    public static QName getPortName(Class<?> implClass, MetadataReader reader, String targetNamespace, boolean isStandard) {
1537        WebService webService = getAnnotation(WebService.class, implClass, reader);
1538        if (isStandard && webService == null) {
1539            throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1540                implClass.getCanonicalName());
1541        }
1542        String name;
1543        if (webService != null && webService.portName().length() > 0) {
1544            name = webService.portName();
1545        } else if (webService != null && webService.name().length() > 0) {
1546            name = webService.name()+PORT;
1547        } else {
1548            name = implClass.getSimpleName()+PORT;
1549        }
1550
1551        if (targetNamespace == null) {
1552            if (webService != null && webService.targetNamespace().length() > 0) {
1553                targetNamespace = webService.targetNamespace();
1554            } else {
1555                String packageName = null;
1556                if (implClass.getPackage() != null) {
1557                    packageName = implClass.getPackage().getName();
1558                }
1559                if (packageName != null) {
1560                    targetNamespace = getNamespace(packageName);
1561                }
1562                if (targetNamespace == null) {
1563                    throw new RuntimeModelerException("runtime.modeler.no.package",
1564                        implClass.getName());
1565                }
1566            }
1567
1568        }
1569
1570        return new QName(targetNamespace, name);
1571    }
1572
1573    static <A extends Annotation> A getAnnotation(Class<A> t, Class<?> cls, MetadataReader reader) {
1574        return (reader == null)? cls.getAnnotation(t) : reader.getAnnotation(t, cls);
1575    }
1576
1577    /**
1578     * Gives portType QName from implementatorClass or SEI
1579     * @param  implOrSeiClass cant be null
1580     * @return  <code>wsdl:portType@name</code>, null if it could not find the annotated class.
1581     */
1582    public static QName getPortTypeName(Class<?> implOrSeiClass){
1583        return getPortTypeName(implOrSeiClass, null, null);
1584    }
1585
1586    public static QName getPortTypeName(Class<?> implOrSeiClass, MetadataReader metadataReader){
1587        return getPortTypeName(implOrSeiClass, null, metadataReader);
1588    }
1589
1590    public static QName getPortTypeName(Class<?> implOrSeiClass, String tns, MetadataReader reader){
1591        assert(implOrSeiClass != null);
1592        WebService webService = getAnnotation(WebService.class, implOrSeiClass, reader);
1593        Class<?> clazz = implOrSeiClass;
1594        if (webService == null)
1595                throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1596                                           implOrSeiClass.getCanonicalName());
1597
1598        if (!implOrSeiClass.isInterface()) {
1599            String epi = webService.endpointInterface();
1600            if (epi.length() > 0) {
1601                try {
1602                    clazz = Thread.currentThread().getContextClassLoader().loadClass(epi);
1603                } catch (ClassNotFoundException e) {
1604                    throw new RuntimeModelerException("runtime.modeler.class.not.found", epi);
1605                }
1606                WebService ws = getAnnotation(WebService.class, clazz, reader);
1607                if (ws == null) {
1608                    throw new RuntimeModelerException("runtime.modeler.endpoint.interface.no.webservice",
1609                                        webService.endpointInterface());
1610                }
1611            }
1612        }
1613
1614        webService = getAnnotation(WebService.class, clazz, reader);
1615        String name = webService.name();
1616        if(name.length() == 0){
1617            name = clazz.getSimpleName();
1618        }
1619        if (tns == null || "".equals(tns.trim())) tns = webService.targetNamespace();
1620        if (tns.length() == 0)
1621            tns = getNamespace(clazz.getPackage().getName());
1622        if (tns == null) {
1623            throw new RuntimeModelerException("runtime.modeler.no.package", clazz.getName());
1624        }
1625        return new QName(tns, name);
1626    }
1627
1628    private ParameterBinding getBinding(String operation, String part, boolean isHeader, Mode mode){
1629        if(binding == null){
1630            if(isHeader)
1631                return ParameterBinding.HEADER;
1632            else
1633                return ParameterBinding.BODY;
1634        }
1635        QName opName = new QName(binding.getBinding().getPortType().getName().getNamespaceURI(), operation);
1636        return binding.getBinding().getBinding(opName, part, mode);
1637    }
1638
1639    private WSDLPart getPart(QName opName, String partName, Mode mode){
1640        if(binding != null){
1641            WSDLBoundOperation bo = binding.getBinding().get(opName);
1642            if(bo != null)
1643                return bo.getPart(partName, mode);
1644        }
1645        return null;
1646    }
1647
1648    /*
1649     * Returns true if an exception is a java.rmi.RemoteException or its subtype.
1650     *
1651     * @param exception
1652     * @return true if an exception is a java.rmi.RemoteException or its subtype,
1653     *      false otherwise
1654     */
1655    private boolean isRemoteException(Class<?> exception) {
1656        Class<?> c = exception;
1657        while (c != null && !REMOTE_EXCEPTION_CLASS.equals(c.getName())) {
1658            c = c.getSuperclass();
1659        }
1660        return c != null;
1661    }
1662
1663    private static Boolean getBooleanSystemProperty(final String prop) {
1664        return AccessController.doPrivileged(
1665            new java.security.PrivilegedAction<Boolean>() {
1666                public Boolean run() {
1667                    String value = System.getProperty(prop);
1668                    return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
1669                }
1670            }
1671        );
1672    }
1673
1674    private static QName getReturnQName(Method method, WebResult webResult, XmlElement xmlElem) {
1675        String webResultName = null;
1676        if (webResult != null && webResult.name().length() > 0) {
1677            webResultName = webResult.name();
1678        }
1679        String xmlElemName = null;
1680        if (xmlElem != null && !xmlElem.name().equals("##default")) {
1681            xmlElemName = xmlElem.name();
1682        }
1683        if (xmlElemName != null && webResultName != null && !xmlElemName.equals(webResultName)) {
1684            throw new RuntimeModelerException("@XmlElement(name)="+xmlElemName+" and @WebResult(name)="+webResultName+" are different for method " +method);
1685        }
1686        String localPart = RETURN;
1687        if (webResultName != null) {
1688            localPart = webResultName;
1689        } else if (xmlElemName != null) {
1690            localPart =  xmlElemName;
1691        }
1692
1693        String webResultNS = null;
1694        if (webResult != null && webResult.targetNamespace().length() > 0) {
1695            webResultNS = webResult.targetNamespace();
1696        }
1697        String xmlElemNS = null;
1698        if (xmlElem != null && !xmlElem.namespace().equals("##default")) {
1699            xmlElemNS = xmlElem.namespace();
1700        }
1701        if (xmlElemNS != null && webResultNS != null && !xmlElemNS.equals(webResultNS)) {
1702            throw new RuntimeModelerException("@XmlElement(namespace)="+xmlElemNS+" and @WebResult(targetNamespace)="+webResultNS+" are different for method " +method);
1703        }
1704        String ns = "";
1705        if (webResultNS != null) {
1706            ns = webResultNS;
1707        } else if (xmlElemNS != null) {
1708            ns =  xmlElemNS;
1709        }
1710
1711        return new QName(ns, localPart);
1712    }
1713
1714    private static QName getParameterQName(Method method, WebParam webParam, XmlElement xmlElem, String paramDefault) {
1715        String webParamName = null;
1716        if (webParam != null && webParam.name().length() > 0) {
1717            webParamName = webParam.name();
1718        }
1719        String xmlElemName = null;
1720        if (xmlElem != null && !xmlElem.name().equals("##default")) {
1721            xmlElemName = xmlElem.name();
1722        }
1723        if (xmlElemName != null && webParamName != null && !xmlElemName.equals(webParamName)) {
1724            throw new RuntimeModelerException("@XmlElement(name)="+xmlElemName+" and @WebParam(name)="+webParamName+" are different for method " +method);
1725        }
1726        String localPart = paramDefault;
1727        if (webParamName != null) {
1728            localPart = webParamName;
1729        } else if (xmlElemName != null) {
1730            localPart =  xmlElemName;
1731        }
1732
1733        String webParamNS = null;
1734        if (webParam != null && webParam.targetNamespace().length() > 0) {
1735            webParamNS = webParam.targetNamespace();
1736        }
1737        String xmlElemNS = null;
1738        if (xmlElem != null && !xmlElem.namespace().equals("##default")) {
1739            xmlElemNS = xmlElem.namespace();
1740        }
1741        if (xmlElemNS != null && webParamNS != null && !xmlElemNS.equals(webParamNS)) {
1742            throw new RuntimeModelerException("@XmlElement(namespace)="+xmlElemNS+" and @WebParam(targetNamespace)="+webParamNS+" are different for method " +method);
1743        }
1744        String ns = "";
1745        if (webParamNS != null) {
1746            ns = webParamNS;
1747        } else if (xmlElemNS != null) {
1748            ns =  xmlElemNS;
1749        }
1750
1751        return new QName(ns, localPart);
1752    }
1753
1754    static public Class erasure(Type type) {
1755        return (Class)REFLECTION_NAVIGATOR.erasure(type);
1756    }
1757}
1758