Thu, 31 Aug 2017 15:18:52 +0800
merge
1 /*
2 * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
26 package com.sun.xml.internal.ws.model;
28 import com.sun.istack.internal.NotNull;
29 import com.sun.istack.internal.localization.Localizable;
30 import com.sun.xml.internal.ws.api.BindingID;
31 import com.sun.xml.internal.ws.api.SOAPVersion;
32 import com.sun.xml.internal.ws.api.WSBinding;
33 import com.sun.xml.internal.ws.api.databinding.DatabindingConfig;
34 import com.sun.xml.internal.ws.api.databinding.MetadataReader;
35 import com.sun.xml.internal.ws.api.model.ExceptionType;
36 import com.sun.xml.internal.ws.api.model.MEP;
37 import com.sun.xml.internal.ws.api.model.Parameter;
38 import com.sun.xml.internal.ws.api.model.ParameterBinding;
39 import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation;
40 import com.sun.xml.internal.ws.api.model.wsdl.WSDLInput;
41 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPart;
42 import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort;
43 import com.sun.xml.internal.ws.binding.WebServiceFeatureList;
44 import com.sun.xml.internal.ws.model.soap.SOAPBindingImpl;
45 import com.sun.xml.internal.ws.resources.ModelerMessages;
46 import com.sun.xml.internal.ws.resources.ServerMessages;
47 import com.sun.xml.internal.ws.spi.db.BindingContext;
48 import com.sun.xml.internal.ws.spi.db.TypeInfo;
49 import com.sun.xml.internal.ws.spi.db.WrapperComposite;
51 import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion;
53 import javax.jws.*;
54 import javax.jws.WebParam.Mode;
55 import javax.jws.soap.SOAPBinding;
56 import javax.jws.soap.SOAPBinding.Style;
57 import javax.xml.bind.annotation.XmlElement;
58 import javax.xml.bind.annotation.XmlSeeAlso;
59 import javax.xml.namespace.QName;
60 import javax.xml.ws.*;
61 import javax.xml.ws.soap.MTOM;
62 import javax.xml.ws.soap.MTOMFeature;
63 import java.lang.annotation.Annotation;
64 import java.lang.reflect.Method;
65 import java.lang.reflect.Modifier;
66 import java.lang.reflect.ParameterizedType;
67 import java.lang.reflect.Type;
68 import java.rmi.RemoteException;
69 import java.security.AccessController;
70 import java.util.HashSet;
71 import java.util.Map;
72 import java.util.Set;
73 import java.util.StringTokenizer;
74 import java.util.TreeMap;
75 import java.util.concurrent.Future;
76 import java.util.logging.Logger;
78 import static javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
80 /**
81 * Creates a runtime model of a SEI (portClass).
82 *
83 * @author WS Developement Team
84 */
85 public 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 Class<RemoteException> REMOTE_EXCEPTION_CLASS = RemoteException.class;
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";
124 /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull BindingID bindingId, @NotNull WebServiceFeature... features) {
125 this(portClass, serviceName, null, bindingId, features);
126 }*/
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 }*/
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 }*/
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 }
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 }
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 }
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 }
210 private <T extends Annotation> T getAnnotation(final Class<?> clazz, final Class<T> T) {
211 return metadataReader.getAnnotation(T, clazz);
212 }
214 private <T extends Annotation> T getAnnotation(final Method method, final Class<T> T) {
215 return metadataReader.getAnnotation(T, method);
216 }
218 private Annotation[] getAnnotations(final Method method) {
219 return metadataReader.getAnnotations(method);
220 }
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 }
229 private static final Logger logger =
230 Logger.getLogger(
231 com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server");
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 }
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);
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 // }
298 if (portName == null) portName = getPortName(portClass, metadataReader, serviceName.getNamespaceURI());
299 model.setPortName(portName);
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());
305 processClass(seiClass);
306 if (model.getJavaMethods().size() == 0)
307 throw new RuntimeModelerException("runtime.modeler.no.operations",
308 portClass.getName());
309 model.postProcess();
311 // Make the configured databinding mode available to the
312 // DatabindingConfig.
313 config.properties().put(BindingContext.class.getName(),
314 model.bindingContext);
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 }
324 private Class configEndpointInterface() {
325 if (config.getEndpointClass() == null ||
326 config.getEndpointClass().isInterface() ) return null; //client proxy Interface
327 return config.getContractClass();
328 }
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 }
348 private boolean noWrapperGen() {
349 Object o = config.properties().get(SuppressDocLitWrapperGeneration);
350 return (o!= null && o instanceof Boolean) ? ((Boolean) o) : false;
351 }
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 }
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 }
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 logger.fine("Dynamically creating exception bean Class " + className);
385 return WrapperBeanGenerator.createExceptionBean(className, exception, targetNamespace, name, namespace, loader, decapitalizeExceptionBeanProperties);
386 }
387 }
389 protected void determineWebMethodUse(Class clazz) {
390 if (clazz == null)
391 return;
392 if (!clazz.isInterface()) {
393 if (clazz == Object.class)
394 return;
395 WebMethod webMethod;
396 for (Method method : clazz.getMethods()) {
397 if (method.getDeclaringClass()!=clazz)
398 continue;
399 webMethod = getAnnotation(method, WebMethod.class);
400 if (webMethod != null && !webMethod.exclude()) {
401 classUsesWebMethod.add(clazz);
402 break;
403 }
404 }
405 }
406 determineWebMethodUse(clazz.getSuperclass());
407 }
409 void processClass(Class clazz) {
410 classUsesWebMethod = new HashSet<Class>();
411 determineWebMethodUse(clazz);
412 WebService webService = getAnnotation(clazz, WebService.class);
413 QName portTypeName = getPortTypeName(clazz, targetNamespace, metadataReader);
414 // String portTypeLocalName = clazz.getSimpleName();
415 // if (webService.name().length() >0)
416 // portTypeLocalName = webService.name();
417 //
418 // targetNamespace = webService.targetNamespace();
419 packageName = "";
420 if (clazz.getPackage() != null)
421 packageName = clazz.getPackage().getName();
422 // if (targetNamespace.length() == 0) {
423 // targetNamespace = getNamespace(packageName);
424 // }
425 // model.setTargetNamespace(targetNamespace);
426 // QName portTypeName = new QName(targetNamespace, portTypeLocalName);
427 targetNamespace = portTypeName.getNamespaceURI();
428 model.setPortTypeName(portTypeName);
429 model.setTargetNamespace(targetNamespace);
430 model.defaultSchemaNamespaceSuffix = config.getMappingInfo().getDefaultSchemaNamespaceSuffix();
431 model.setWSDLLocation(webService.wsdlLocation());
433 SOAPBinding soapBinding = getAnnotation(clazz, SOAPBinding.class);
434 if (soapBinding != null) {
435 if (soapBinding.style() == SOAPBinding.Style.RPC && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
436 throw new RuntimeModelerException("runtime.modeler.invalid.soapbinding.parameterstyle",
437 soapBinding, clazz);
439 }
440 isWrapped = soapBinding.parameterStyle()== WRAPPED;
441 }
442 defaultBinding = createBinding(soapBinding);
443 /*
444 * if clazz != portClass then there is an SEI. If there is an
445 * SEI, then all methods should be processed. However, if there is
446 * no SEI, and the implementation class uses at least one
447 * WebMethod annotation, then only methods with this annotation
448 * will be processed.
449 */
450 /* if (clazz == portClass) {
451 WebMethod webMethod;
452 for (Method method : clazz.getMethods()) {
453 webMethod = getPrivMethodAnnotation(method, WebMethod.class);
454 if (webMethod != null &&
455 !webMethod.exclude()) {
456 usesWebMethod = true;
457 break;
458 }
459 }
460 }*/
462 for (Method method : clazz.getMethods()) {
463 if (!clazz.isInterface()) { // if clazz is SEI, then all methods are web methods
464 if (method.getDeclaringClass() == Object.class) continue;
465 if (!getBooleanSystemProperty("com.sun.xml.internal.ws.legacyWebMethod")) { // legacy webMethod computation behaviour to be used
466 if (!isWebMethodBySpec(method, clazz))
467 continue;
468 } else {
469 if (!isWebMethod(method))
470 continue;
471 }
472 }
473 // TODO: binding can be null. We need to figure out how to post-process
474 // RuntimeModel to link to WSDLModel
475 processMethod(method);
476 }
477 //Add additional jaxb classes referenced by {@link XmlSeeAlso}
478 XmlSeeAlso xmlSeeAlso = getAnnotation(clazz, XmlSeeAlso.class);
479 if(xmlSeeAlso != null)
480 model.addAdditionalClasses(xmlSeeAlso.value());
481 }
483 /*
484 * Section 3.3 of spec
485 * Otherwise, the class implicitly defines a service endpoint interface (SEI) which
486 * comprises all of the public methods that satisfy one of the following conditions:
487 * 1. They are annotated with the javax.jws.WebMethod annotation with the exclude element set to
488 * false or missing (since false is the default for this annotation element).
489 * 2. They are not annotated with the javax.jws.WebMethod annotation but their declaring class has a
490 * javax.jws.WebService annotation.
491 *
492 * also the method should non-static or non-final
493 */
494 private boolean isWebMethodBySpec(Method method, Class clazz) {
496 int modifiers = method.getModifiers();
497 boolean staticFinal = Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers);
499 assert Modifier.isPublic(modifiers);
500 assert !clazz.isInterface();
502 WebMethod webMethod = getAnnotation(method, WebMethod.class);
503 if (webMethod != null) {
504 if (webMethod.exclude()) {
505 return false; // @WebMethod(exclude="true")
506 }
507 if (staticFinal) {
508 throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATICFINAL(method));
509 }
510 return true; // @WebMethod
511 }
513 if (staticFinal) {
514 return false;
515 }
517 Class declClass = method.getDeclaringClass();
518 return getAnnotation(declClass, WebService.class) != null;
519 }
521 private boolean isWebMethod(Method method) {
522 int modifiers = method.getModifiers();
523 if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers))
524 return false;
526 Class clazz = method.getDeclaringClass();
527 boolean declHasWebService = getAnnotation(clazz, WebService.class) != null;
528 WebMethod webMethod = getAnnotation(method, WebMethod.class);
529 if (webMethod != null && !webMethod.exclude() && declHasWebService)
530 return true;
531 return declHasWebService && !classUsesWebMethod.contains(clazz);
532 }
534 /**
535 * creates a runtime model <code>SOAPBinding</code> from a <code>javax.jws.soap.SOAPBinding</code> object
536 * @param soapBinding the <code>javax.jws.soap.SOAPBinding</code> to model
537 * @return returns the runtime model SOAPBinding corresponding to <code>soapBinding</code>
538 */
539 protected SOAPBindingImpl createBinding(SOAPBinding soapBinding) {
540 SOAPBindingImpl rtSOAPBinding = new SOAPBindingImpl();
541 Style style = soapBinding!=null ? soapBinding.style() : Style.DOCUMENT;
542 rtSOAPBinding.setStyle(style);
543 assert bindingId != null;
544 model.bindingId = bindingId;
545 SOAPVersion soapVersion = bindingId.getSOAPVersion();
546 rtSOAPBinding.setSOAPVersion(soapVersion);
547 return rtSOAPBinding;
548 }
550 /**
551 * gets the namespace <code>String</code> for a given <code>packageName</code>
552 * @param packageName the name of the package used to find a namespace.
553 * can be empty.
554 * @return the namespace for the specified <code>packageName</code>
555 */
556 public static String getNamespace(@NotNull String packageName) {
557 if (packageName.length() == 0)
558 return null;
560 StringTokenizer tokenizer = new StringTokenizer(packageName, ".");
561 String[] tokens;
562 if (tokenizer.countTokens() == 0) {
563 tokens = new String[0];
564 } else {
565 tokens = new String[tokenizer.countTokens()];
566 for (int i=tokenizer.countTokens()-1; i >= 0; i--) {
567 tokens[i] = tokenizer.nextToken();
568 }
569 }
570 StringBuilder namespace = new StringBuilder("http://");
571 for (int i=0; i<tokens.length; i++) {
572 if (i!=0)
573 namespace.append('.');
574 namespace.append(tokens[i]);
575 }
576 namespace.append('/');
577 return namespace.toString();
578 }
580 /*
581 * Returns true if an exception is service specific exception as per JAX-WS rules.
582 * @param exception
583 * @return
584 */
585 private boolean isServiceException(Class<?> exception) {
586 return EXCEPTION_CLASS.isAssignableFrom(exception) &&
587 !(RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || REMOTE_EXCEPTION_CLASS.isAssignableFrom(exception));
588 }
590 /**
591 * creates the runtime model for a method on the <code>portClass</code>
592 * @param method the method to model
593 */
594 private void processMethod(Method method) {
595 // int mods = method.getModifiers();
596 WebMethod webMethod = getAnnotation(method, WebMethod.class);
597 if (webMethod != null && webMethod.exclude()) return;
598 /*
599 validations are already done
601 if (!Modifier.isPublic(mods) || Modifier.isStatic(mods)) {
602 if(webMethod != null) {
603 // if the user put @WebMethod on these non-qualifying method,
604 // it's an error
605 if(Modifier.isStatic(mods))
606 throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATIC(method));
607 else
608 throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_PUBLIC(method));
609 }
610 return;
611 }
613 if (webMethod != null && webMethod.exclude())
614 return;
615 */
617 String methodName = method.getName();
618 boolean isOneway = (getAnnotation(method, Oneway.class) != null);
620 //Check that oneway methods don't thorw any checked exceptions
621 if (isOneway) {
622 for (Class<?> exception : method.getExceptionTypes()) {
623 if(isServiceException(exception)) {
624 throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.checked.exceptions",
625 portClass.getCanonicalName(), methodName, exception.getName());
626 }
627 }
628 }
630 JavaMethodImpl javaMethod;
631 //Class implementorClass = portClass;
632 if (method.getDeclaringClass()==portClass) {
633 javaMethod = new JavaMethodImpl(model,method,method,metadataReader);
634 } else {
635 try {
636 Method tmpMethod = portClass.getMethod(method.getName(),
637 method.getParameterTypes());
638 javaMethod = new JavaMethodImpl(model,tmpMethod,method,metadataReader);
639 } catch (NoSuchMethodException e) {
640 throw new RuntimeModelerException("runtime.modeler.method.not.found",
641 method.getName(), portClass.getName());
642 }
643 }
647 //set MEP -oneway, async, req/resp
648 MEP mep = getMEP(method);
649 javaMethod.setMEP(mep);
651 String action = null;
654 String operationName = method.getName();
655 if (webMethod != null ) {
656 action = webMethod.action();
657 operationName = webMethod.operationName().length() > 0 ?
658 webMethod.operationName() :
659 operationName;
660 }
662 //override the @WebMethod.action value by the one from the WSDL
663 if(binding != null){
664 WSDLBoundOperation bo = binding.getBinding().get(new QName(targetNamespace, operationName));
665 if(bo != null){
666 WSDLInput wsdlInput = bo.getOperation().getInput();
667 String wsaAction = wsdlInput.getAction();
668 if(wsaAction != null && !wsdlInput.isDefaultAction())
669 action = wsaAction;
670 else
671 action = bo.getSOAPAction();
672 }
673 }
675 javaMethod.setOperationQName(new QName(targetNamespace,operationName));
676 SOAPBinding methodBinding = getAnnotation(method, SOAPBinding.class);
677 if(methodBinding != null && methodBinding.style() == SOAPBinding.Style.RPC) {
678 logger.warning(ModelerMessages.RUNTIMEMODELER_INVALID_SOAPBINDING_ON_METHOD(methodBinding, method.getName(), method.getDeclaringClass().getName()));
679 } else if (methodBinding == null && !method.getDeclaringClass().equals(portClass)) {
680 methodBinding = getAnnotation(method.getDeclaringClass(), SOAPBinding.class);
681 if (methodBinding != null && methodBinding.style() == SOAPBinding.Style.RPC && methodBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) {
682 throw new RuntimeModelerException("runtime.modeler.invalid.soapbinding.parameterstyle",
683 methodBinding, method.getDeclaringClass());
684 }
685 }
687 if(methodBinding!= null && defaultBinding.getStyle() != methodBinding.style()) {
688 throw new RuntimeModelerException("runtime.modeler.soapbinding.conflict",
689 methodBinding.style(), method.getName(),defaultBinding.getStyle());
690 }
692 boolean methodIsWrapped = isWrapped;
693 Style style = defaultBinding.getStyle();
694 if (methodBinding != null) {
695 SOAPBindingImpl mySOAPBinding = createBinding(methodBinding);
696 style = mySOAPBinding.getStyle();
697 if (action != null)
698 mySOAPBinding.setSOAPAction(action);
699 methodIsWrapped = methodBinding.parameterStyle().equals(
700 WRAPPED);
701 javaMethod.setBinding(mySOAPBinding);
702 } else {
703 SOAPBindingImpl sb = new SOAPBindingImpl(defaultBinding);
704 if (action != null) {
705 sb.setSOAPAction(action);
706 } else {
707 String defaults = SOAPVersion.SOAP_11 == sb.getSOAPVersion() ? "" : null;
708 sb.setSOAPAction(defaults);
709 }
710 javaMethod.setBinding(sb);
711 }
712 if (!methodIsWrapped) {
713 processDocBareMethod(javaMethod, operationName, method);
714 } else if (style.equals(Style.DOCUMENT)) {
715 processDocWrappedMethod(javaMethod, methodName, operationName,
716 method);
717 } else {
718 processRpcMethod(javaMethod, methodName, operationName, method);
719 }
720 model.addJavaMethod(javaMethod);
721 }
723 private MEP getMEP(Method m){
724 if (getAnnotation(m, Oneway.class)!= null) {
725 return MEP.ONE_WAY;
726 }
727 if(Response.class.isAssignableFrom(m.getReturnType())){
728 return MEP.ASYNC_POLL;
729 }else if(Future.class.isAssignableFrom(m.getReturnType())){
730 return MEP.ASYNC_CALLBACK;
731 }
732 return MEP.REQUEST_RESPONSE;
733 }
735 /**
736 * models a document/literal wrapped method
737 * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
738 * @param methodName the runtime model <code>JavaMethod</code> instance being created
739 * @param operationName the runtime model <code>JavaMethod</code> instance being created
740 * @param method the <code>method</code> to model
741 */
742 protected void processDocWrappedMethod(JavaMethodImpl javaMethod, String methodName,
743 String operationName, Method method) {
744 boolean methodHasHeaderParams = false;
745 boolean isOneway = getAnnotation(method, Oneway.class)!= null;
746 RequestWrapper reqWrapper = getAnnotation(method,RequestWrapper.class);
747 ResponseWrapper resWrapper = getAnnotation(method,ResponseWrapper.class);
748 String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
749 if (packageName == null || packageName.length() == 0) {
750 beanPackage = JAXWS_PACKAGE_PD;
751 }
752 String requestClassName;
753 if(reqWrapper != null && reqWrapper.className().length()>0){
754 requestClassName = reqWrapper.className();
755 }else{
756 requestClassName = beanPackage + capitalize(method.getName());
757 }
760 String responseClassName;
761 if(resWrapper != null && resWrapper.className().length()>0){
762 responseClassName = resWrapper.className();
763 }else{
764 responseClassName = beanPackage + capitalize(method.getName()) + RESPONSE;
765 }
767 String reqName = operationName;
768 String reqNamespace = targetNamespace;
769 String reqPartName = "parameters";
770 if (reqWrapper != null) {
771 if (reqWrapper.targetNamespace().length() > 0)
772 reqNamespace = reqWrapper.targetNamespace();
773 if (reqWrapper.localName().length() > 0)
774 reqName = reqWrapper.localName();
775 try {
776 if (reqWrapper.partName().length() > 0)
777 reqPartName = reqWrapper.partName();
778 } catch(LinkageError e) {
779 //2.1 API dopes n't have this method
780 //Do nothing, just default to "parameters"
781 }
782 }
783 QName reqElementName = new QName(reqNamespace, reqName);
784 javaMethod.setRequestPayloadName(reqElementName);
785 Class requestClass = getRequestWrapperClass(requestClassName, method, reqElementName);
787 Class responseClass = null;
788 String resName = operationName+"Response";
789 String resNamespace = targetNamespace;
790 QName resElementName = null;
791 String resPartName = "parameters";
792 if (!isOneway) {
793 if (resWrapper != null) {
794 if (resWrapper.targetNamespace().length() > 0)
795 resNamespace = resWrapper.targetNamespace();
796 if (resWrapper.localName().length() > 0)
797 resName = resWrapper.localName();
798 try {
799 if (resWrapper.partName().length() > 0)
800 resPartName = resWrapper.partName();
801 } catch (LinkageError e) {
802 //2.1 API does n't have this method
803 //Do nothing, just default to "parameters"
804 }
805 }
806 resElementName = new QName(resNamespace, resName);
807 responseClass = getResponseWrapperClass(responseClassName, method, resElementName);
808 }
810 TypeInfo typeRef =
811 new TypeInfo(reqElementName, requestClass);
812 typeRef.setNillable(false);
813 WrapperParameter requestWrapper = new WrapperParameter(javaMethod, typeRef,
814 Mode.IN, 0);
815 requestWrapper.setPartName(reqPartName);
816 requestWrapper.setBinding(ParameterBinding.BODY);
817 javaMethod.addParameter(requestWrapper);
818 WrapperParameter responseWrapper = null;
819 if (!isOneway) {
820 typeRef = new TypeInfo(resElementName, responseClass);
821 typeRef.setNillable(false);
822 responseWrapper = new WrapperParameter(javaMethod, typeRef, Mode.OUT, -1);
823 javaMethod.addParameter(responseWrapper);
824 responseWrapper.setBinding(ParameterBinding.BODY);
825 }
827 // return value
830 WebResult webResult = getAnnotation(method, WebResult.class);
831 XmlElement xmlElem = getAnnotation(method, XmlElement.class);
832 QName resultQName = getReturnQName(method, webResult, xmlElem);
833 Class returnType = method.getReturnType();
834 boolean isResultHeader = false;
835 if (webResult != null) {
836 isResultHeader = webResult.header();
837 methodHasHeaderParams = isResultHeader || methodHasHeaderParams;
838 if (isResultHeader && xmlElem != null) {
839 throw new RuntimeModelerException("@XmlElement cannot be specified on method "+method+" as the return value is bound to header");
840 }
841 if (resultQName.getNamespaceURI().length() == 0 && webResult.header()) {
842 // headers must have a namespace
843 resultQName = new QName(targetNamespace, resultQName.getLocalPart());
844 }
845 }
847 if(javaMethod.isAsync()){
848 returnType = getAsyncReturnType(method, returnType);
849 resultQName = new QName(RETURN);
850 }
851 resultQName = qualifyWrappeeIfNeeded(resultQName, resNamespace);
852 if (!isOneway && (returnType != null) && (!returnType.getName().equals("void"))) {
853 Annotation[] rann = getAnnotations(method);
854 if (resultQName.getLocalPart() != null) {
855 TypeInfo rTypeReference = new TypeInfo(resultQName, returnType, rann);
856 metadataReader.getProperties(rTypeReference.properties(), method);
857 rTypeReference.setGenericType(method.getGenericReturnType());
858 ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1);
859 if (isResultHeader) {
860 returnParameter.setBinding(ParameterBinding.HEADER);
861 javaMethod.addParameter(returnParameter);
862 } else {
863 returnParameter.setBinding(ParameterBinding.BODY);
864 responseWrapper.addWrapperChild(returnParameter);
865 }
866 }
867 }
869 //get WebParam
870 Class<?>[] parameterTypes = method.getParameterTypes();
871 Type[] genericParameterTypes = method.getGenericParameterTypes();
872 Annotation[][] pannotations = getParamAnnotations(method);
873 int pos = 0;
874 for (Class clazzType : parameterTypes) {
875 String partName=null;
876 String paramName = "arg"+pos;
877 //String paramNamespace = "";
878 boolean isHeader = false;
880 if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
881 continue;
882 }
884 boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
885 //set the actual type argument of Holder in the TypeReference
886 if (isHolder) {
887 if(clazzType==Holder.class){
888 clazzType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]);
889 }
890 }
891 Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
892 WebParam webParam = null;
893 xmlElem = null;
894 for (Annotation annotation : pannotations[pos]) {
895 if (annotation.annotationType() == WebParam.class)
896 webParam = (WebParam)annotation;
897 else if (annotation.annotationType() == XmlElement.class)
898 xmlElem = (XmlElement)annotation;
899 }
901 QName paramQName = getParameterQName(method, webParam, xmlElem, paramName);
902 if (webParam != null) {
903 isHeader = webParam.header();
904 methodHasHeaderParams = isHeader || methodHasHeaderParams;
905 if (isHeader && xmlElem != null) {
906 throw new RuntimeModelerException("@XmlElement cannot be specified on method "+method+" parameter that is bound to header");
907 }
908 if(webParam.partName().length() > 0)
909 partName = webParam.partName();
910 else
911 partName = paramQName.getLocalPart();
912 if (isHeader && paramQName.getNamespaceURI().equals("")) { // headers cannot be in empty namespace
913 paramQName = new QName(targetNamespace, paramQName.getLocalPart());
914 }
915 paramMode = webParam.mode();
916 if (isHolder && paramMode == Mode.IN)
917 paramMode = Mode.INOUT;
918 }
919 paramQName = qualifyWrappeeIfNeeded(paramQName, reqNamespace);
920 typeRef =
921 new TypeInfo(paramQName, clazzType, pannotations[pos]);
922 metadataReader.getProperties(typeRef.properties(), method, pos);
923 typeRef.setGenericType(genericParameterTypes[pos]);
924 ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++);
926 if (isHeader) {
927 param.setBinding(ParameterBinding.HEADER);
928 javaMethod.addParameter(param);
929 param.setPartName(partName);
930 } else {
931 param.setBinding(ParameterBinding.BODY);
932 if (paramMode!=Mode.OUT) {
933 requestWrapper.addWrapperChild(param);
934 }
935 if (paramMode!=Mode.IN) {
936 if (isOneway) {
937 throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.out.parameters",
938 portClass.getCanonicalName(), methodName);
939 }
940 responseWrapper.addWrapperChild(param);
941 }
942 }
943 }
945 //If the method has any parameter or return type that is bound to a header, use "result" as part name to avoid
946 // name collison of same input part name and output part name ("parameters") shown up as param names on the
947 // client mapping.
948 if(methodHasHeaderParams) {
949 resPartName = "result";
950 }
951 if(responseWrapper != null)
952 responseWrapper.setPartName(resPartName);
953 processExceptions(javaMethod, method);
954 }
956 private QName qualifyWrappeeIfNeeded(QName resultQName, String ns) {
957 Object o = config.properties().get(DocWrappeeNamespapceQualified);
958 boolean qualified = (o!= null && o instanceof Boolean) ? ((Boolean) o) : false;
959 if (qualified) {
960 if (resultQName.getNamespaceURI() == null || "".equals(resultQName.getNamespaceURI())) {
961 return new QName(ns, resultQName.getLocalPart());
962 }
963 }
964 return resultQName;
965 }
967 /**
968 * models a rpc/literal method
969 * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
970 * @param methodName the name of the <code>method</code> being modeled.
971 * @param operationName the WSDL operation name for this <code>method</code>
972 * @param method the runtime model <code>JavaMethod</code> instance being created
973 */
974 protected void processRpcMethod(JavaMethodImpl javaMethod, String methodName,
975 String operationName, Method method) {
976 boolean isOneway = getAnnotation(method, Oneway.class) != null;
978 // use Map to build parameters in the part order when they are known.
979 // if part is unbound, we just put them at the end, and for that we
980 // use a large index (10000+) to avoid colliding with ordered ones.
981 // this assumes that there's no operation with # of parameters > 10000,
982 // but I think it's a pretty safe assumption - KK.
983 Map<Integer, ParameterImpl> resRpcParams = new TreeMap<Integer, ParameterImpl>();
984 Map<Integer, ParameterImpl> reqRpcParams = new TreeMap<Integer, ParameterImpl>();
986 //Lets take the service namespace and overwrite it with the one we get it from wsdl
987 String reqNamespace = targetNamespace;
988 String respNamespace = targetNamespace;
990 if(binding != null && Style.RPC.equals(binding.getBinding().getStyle())){
991 QName opQName = new QName(binding.getBinding().getPortTypeName().getNamespaceURI(), operationName);
992 WSDLBoundOperation op = binding.getBinding().get(opQName);
993 if(op != null){
994 //it cant be null, but lets not fail and try to work with service namespce
995 if(op.getRequestNamespace() != null){
996 reqNamespace = op.getRequestNamespace();
997 }
999 //it cant be null, but lets not fail and try to work with service namespce
1000 if(op.getResponseNamespace() != null){
1001 respNamespace = op.getResponseNamespace();
1002 }
1003 }
1004 }
1006 QName reqElementName = new QName(reqNamespace, operationName);
1007 javaMethod.setRequestPayloadName(reqElementName);
1008 QName resElementName = null;
1009 if (!isOneway) {
1010 resElementName = new QName(respNamespace, operationName+RESPONSE);
1011 }
1013 Class wrapperType = WrapperComposite.class;
1014 TypeInfo typeRef = new TypeInfo(reqElementName, wrapperType);
1015 WrapperParameter requestWrapper = new WrapperParameter(javaMethod, typeRef, Mode.IN, 0);
1016 requestWrapper.setInBinding(ParameterBinding.BODY);
1017 javaMethod.addParameter(requestWrapper);
1018 WrapperParameter responseWrapper = null;
1019 if (!isOneway) {
1020 typeRef = new TypeInfo(resElementName, wrapperType);
1021 responseWrapper = new WrapperParameter(javaMethod, typeRef, Mode.OUT, -1);
1022 responseWrapper.setOutBinding(ParameterBinding.BODY);
1023 javaMethod.addParameter(responseWrapper);
1024 }
1026 Class returnType = method.getReturnType();
1027 String resultName = RETURN;
1028 String resultTNS = targetNamespace;
1029 String resultPartName = resultName;
1030 boolean isResultHeader = false;
1031 WebResult webResult = getAnnotation(method, WebResult.class);
1033 if (webResult != null) {
1034 isResultHeader = webResult.header();
1035 if (webResult.name().length() > 0)
1036 resultName = webResult.name();
1037 if (webResult.partName().length() > 0) {
1038 resultPartName = webResult.partName();
1039 if (!isResultHeader)
1040 resultName = resultPartName;
1041 } else
1042 resultPartName = resultName;
1043 if (webResult.targetNamespace().length() > 0)
1044 resultTNS = webResult.targetNamespace();
1045 isResultHeader = webResult.header();
1046 }
1047 QName resultQName;
1048 if (isResultHeader)
1049 resultQName = new QName(resultTNS, resultName);
1050 else
1051 resultQName = new QName(resultName);
1053 if(javaMethod.isAsync()){
1054 returnType = getAsyncReturnType(method, returnType);
1055 }
1057 if (!isOneway && returnType!=null && returnType!=void.class) {
1058 Annotation[] rann = getAnnotations(method);
1059 TypeInfo rTypeReference = new TypeInfo(resultQName, returnType, rann);
1060 metadataReader.getProperties(rTypeReference.properties(), method);
1061 rTypeReference.setGenericType(method.getGenericReturnType());
1062 ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1);
1063 returnParameter.setPartName(resultPartName);
1064 if(isResultHeader){
1065 returnParameter.setBinding(ParameterBinding.HEADER);
1066 javaMethod.addParameter(returnParameter);
1067 rTypeReference.setGlobalElement(true);
1068 }else{
1069 ParameterBinding rb = getBinding(operationName, resultPartName, false, Mode.OUT);
1070 returnParameter.setBinding(rb);
1071 if(rb.isBody()){
1072 rTypeReference.setGlobalElement(false);
1073 WSDLPart p = getPart(new QName(targetNamespace,operationName), resultPartName, Mode.OUT);
1074 if(p == null)
1075 resRpcParams.put(resRpcParams.size()+10000, returnParameter);
1076 else
1077 resRpcParams.put(p.getIndex(), returnParameter);
1078 }else{
1079 javaMethod.addParameter(returnParameter);
1080 }
1081 }
1082 }
1084 //get WebParam
1085 Class<?>[] parameterTypes = method.getParameterTypes();
1086 Type[] genericParameterTypes = method.getGenericParameterTypes();
1087 Annotation[][] pannotations = getParamAnnotations(method);
1088 int pos = 0;
1089 for (Class clazzType : parameterTypes) {
1090 String paramName = "";
1091 String paramNamespace = "";
1092 String partName = "";
1093 boolean isHeader = false;
1095 if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
1096 continue;
1097 }
1099 boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
1100 //set the actual type argument of Holder in the TypeReference
1101 if (isHolder) {
1102 if (clazzType==Holder.class)
1103 clazzType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]);
1104 }
1105 Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
1106 for (Annotation annotation : pannotations[pos]) {
1107 if (annotation.annotationType() == javax.jws.WebParam.class) {
1108 javax.jws.WebParam webParam = (javax.jws.WebParam) annotation;
1109 paramName = webParam.name();
1110 partName = webParam.partName();
1111 isHeader = webParam.header();
1112 WebParam.Mode mode = webParam.mode();
1113 paramNamespace = webParam.targetNamespace();
1114 if (isHolder && mode == Mode.IN)
1115 mode = Mode.INOUT;
1116 paramMode = mode;
1117 break;
1118 }
1119 }
1121 if (paramName.length() == 0) {
1122 paramName = "arg"+pos;
1123 }
1124 if (partName.length() == 0) {
1125 partName = paramName;
1126 } else if (!isHeader) {
1127 paramName = partName;
1128 }
1129 if (partName.length() == 0) {
1130 partName = paramName;
1131 }
1133 QName paramQName;
1134 if (!isHeader) {
1135 //its rpclit body param, set namespace to ""
1136 paramQName = new QName("", paramName);
1137 } else {
1138 if (paramNamespace.length() == 0)
1139 paramNamespace = targetNamespace;
1140 paramQName = new QName(paramNamespace, paramName);
1141 }
1142 typeRef =
1143 new TypeInfo(paramQName, clazzType, pannotations[pos]);
1144 metadataReader.getProperties(typeRef.properties(), method, pos);
1145 typeRef.setGenericType(genericParameterTypes[pos]);
1146 ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++);
1147 param.setPartName(partName);
1149 if(paramMode == Mode.INOUT){
1150 ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN);
1151 param.setInBinding(pb);
1152 pb = getBinding(operationName, partName, isHeader, Mode.OUT);
1153 param.setOutBinding(pb);
1154 }else{
1155 if (isHeader) {
1156 typeRef.setGlobalElement(true);
1157 param.setBinding(ParameterBinding.HEADER);
1158 } else {
1159 ParameterBinding pb = getBinding(operationName, partName, false, paramMode);
1160 param.setBinding(pb);
1161 }
1162 }
1163 if(param.getInBinding().isBody()){
1164 typeRef.setGlobalElement(false);
1165 if(!param.isOUT()){
1166 WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.IN);
1167 if(p == null)
1168 reqRpcParams.put(reqRpcParams.size()+10000, param);
1169 else
1170 reqRpcParams.put(p.getIndex(), param);
1171 }
1173 if(!param.isIN()){
1174 if (isOneway) {
1175 throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.out.parameters",
1176 portClass.getCanonicalName(), methodName);
1177 }
1178 WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.OUT);
1179 if(p == null)
1180 resRpcParams.put(resRpcParams.size()+10000, param);
1181 else
1182 resRpcParams.put(p.getIndex(), param);
1183 }
1184 }else{
1185 javaMethod.addParameter(param);
1186 }
1187 }
1188 for (ParameterImpl p : reqRpcParams.values())
1189 requestWrapper.addWrapperChild(p);
1190 for (ParameterImpl p : resRpcParams.values())
1191 responseWrapper.addWrapperChild(p);
1192 processExceptions(javaMethod, method);
1193 }
1195 /**
1196 * models the exceptions thrown by <code>method</code> and adds them to the <code>javaMethod</code>
1197 * runtime model object
1198 * @param javaMethod the runtime model object to add the exception model objects to
1199 * @param method the <code>method</code> from which to find the exceptions to model
1200 */
1201 protected void processExceptions(JavaMethodImpl javaMethod, Method method) {
1202 Action actionAnn = getAnnotation(method, Action.class);
1203 FaultAction[] faultActions = {};
1204 if(actionAnn != null)
1205 faultActions = actionAnn.fault();
1206 for (Class<?> exception : method.getExceptionTypes()) {
1208 //Exclude RuntimeException, RemoteException and Error etc
1209 if (!EXCEPTION_CLASS.isAssignableFrom(exception))
1210 continue;
1211 if (RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || REMOTE_EXCEPTION_CLASS.isAssignableFrom(exception))
1212 continue;
1214 Class exceptionBean;
1215 Annotation[] anns;
1216 WebFault webFault = getAnnotation(exception, WebFault.class);
1217 Method faultInfoMethod = getWSDLExceptionFaultInfo(exception);
1218 ExceptionType exceptionType = ExceptionType.WSDLException;
1219 String namespace = targetNamespace;
1220 String name = exception.getSimpleName();
1221 String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
1222 if (packageName.length() == 0)
1223 beanPackage = JAXWS_PACKAGE_PD;
1224 String className = beanPackage+ name + BEAN;
1225 String messageName = exception.getSimpleName();
1226 if (webFault != null) {
1227 if (webFault.faultBean().length()>0)
1228 className = webFault.faultBean();
1229 if (webFault.name().length()>0)
1230 name = webFault.name();
1231 if (webFault.targetNamespace().length()>0)
1232 namespace = webFault.targetNamespace();
1233 if (webFault.messageName().length()>0)
1234 messageName = webFault.messageName();
1235 }
1236 if (faultInfoMethod == null) {
1237 exceptionBean = getExceptionBeanClass(className, exception, name, namespace);
1238 exceptionType = ExceptionType.UserDefined;
1239 anns = getAnnotations(exceptionBean);
1240 } else {
1241 exceptionBean = faultInfoMethod.getReturnType();
1242 anns = getAnnotations(faultInfoMethod);
1243 }
1244 QName faultName = new QName(namespace, name);
1245 TypeInfo typeRef = new TypeInfo(faultName, exceptionBean, anns);
1246 CheckedExceptionImpl checkedException =
1247 new CheckedExceptionImpl(javaMethod, exception, typeRef, exceptionType);
1248 checkedException.setMessageName(messageName);
1249 for(FaultAction fa: faultActions) {
1250 if(fa.className().equals(exception) && !fa.value().equals("")) {
1251 checkedException.setFaultAction(fa.value());
1252 break;
1253 }
1254 }
1255 javaMethod.addException(checkedException);
1256 }
1257 }
1259 /**
1260 * returns the method that corresponds to "getFaultInfo". Returns null if this is not an
1261 * exception generated from a WSDL
1262 * @param exception the class to search for the "getFaultInfo" method
1263 * @return the method named "getFaultInfo" if this is an exception generated from WSDL or an
1264 * exception that contains the <code>WebFault</code> annotation. Otherwise it returns null
1265 */
1266 protected Method getWSDLExceptionFaultInfo(Class exception) {
1267 // if (!exception.isAnnotationPresent(WebFault.class))
1268 if (getAnnotation(exception, WebFault.class) == null)
1269 return null;
1270 try {
1271 return exception.getMethod("getFaultInfo");
1272 } catch (NoSuchMethodException e) {
1273 return null;
1274 }
1275 }
1277 /**
1278 * models a document/literal bare method
1279 * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
1280 * @param operationName the runtime model <code>JavaMethod</code> instance being created
1281 * @param method the runtime model <code>JavaMethod</code> instance being created
1282 */
1283 protected void processDocBareMethod(JavaMethodImpl javaMethod,
1284 String operationName, Method method) {
1286 String resultName = operationName+RESPONSE;
1287 String resultTNS = targetNamespace;
1288 String resultPartName = null;
1289 boolean isResultHeader = false;
1290 WebResult webResult = getAnnotation(method, WebResult.class);
1291 if (webResult != null) {
1292 if (webResult.name().length() > 0)
1293 resultName = webResult.name();
1294 if (webResult.targetNamespace().length() > 0)
1295 resultTNS = webResult.targetNamespace();
1296 resultPartName = webResult.partName();
1297 isResultHeader = webResult.header();
1298 }
1300 Class returnType = method.getReturnType();
1301 Type gReturnType = method.getGenericReturnType();
1302 if(javaMethod.isAsync()){
1303 returnType = getAsyncReturnType(method, returnType);
1304 }
1306 if ((returnType != null) && (!returnType.getName().equals("void"))) {
1307 Annotation[] rann = getAnnotations(method);
1308 if (resultName != null) {
1309 QName responseQName = new QName(resultTNS, resultName);
1310 TypeInfo rTypeReference = new TypeInfo(responseQName, returnType, rann);
1311 rTypeReference.setGenericType(gReturnType);
1312 metadataReader.getProperties(rTypeReference.properties(), method);
1313 ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1);
1315 if(resultPartName == null || (resultPartName.length() == 0)){
1316 resultPartName = resultName;
1317 }
1318 returnParameter.setPartName(resultPartName);
1319 if(isResultHeader){
1320 returnParameter.setBinding(ParameterBinding.HEADER);
1321 }else{
1322 ParameterBinding rb = getBinding(operationName, resultPartName, false, Mode.OUT);
1323 returnParameter.setBinding(rb);
1324 }
1325 javaMethod.addParameter(returnParameter);
1326 }
1327 }
1329 //get WebParam
1330 Class<?>[] parameterTypes = method.getParameterTypes();
1331 Type[] genericParameterTypes = method.getGenericParameterTypes();
1332 Annotation[][] pannotations = getParamAnnotations(method);
1333 int pos = 0;
1334 for (Class clazzType : parameterTypes) {
1335 String paramName = operationName; //method.getName();
1336 String partName = null;
1337 String requestNamespace = targetNamespace;
1338 boolean isHeader = false;
1340 //async
1341 if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
1342 continue;
1343 }
1345 boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
1346 //set the actual type argument of Holder in the TypeReference
1347 if (isHolder) {
1348 if (clazzType==Holder.class)
1349 clazzType = (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]);
1350 }
1352 Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
1353 for (Annotation annotation : pannotations[pos]) {
1354 if (annotation.annotationType() == javax.jws.WebParam.class) {
1355 javax.jws.WebParam webParam = (javax.jws.WebParam) annotation;
1356 paramMode = webParam.mode();
1357 if (isHolder && paramMode == Mode.IN)
1358 paramMode = Mode.INOUT;
1359 isHeader = webParam.header();
1360 if(isHeader)
1361 paramName = "arg"+pos;
1362 if(paramMode == Mode.OUT && !isHeader)
1363 paramName = operationName+RESPONSE;
1364 if (webParam.name().length() > 0)
1365 paramName = webParam.name();
1366 partName = webParam.partName();
1367 if (!webParam.targetNamespace().equals("")) {
1368 requestNamespace = webParam.targetNamespace();
1369 }
1370 break;
1371 }
1372 }
1374 QName requestQName = new QName(requestNamespace, paramName);
1375 if (!isHeader && paramMode != Mode.OUT) javaMethod.setRequestPayloadName(requestQName);
1376 //doclit/wrapped
1377 TypeInfo typeRef = //operationName with upper 1 char
1378 new TypeInfo(requestQName, clazzType,
1379 pannotations[pos]);
1380 metadataReader.getProperties(typeRef.properties(), method, pos);
1381 typeRef.setGenericType(genericParameterTypes[pos]);
1382 ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++);
1383 if(partName == null || (partName.length() == 0)){
1384 partName = paramName;
1385 }
1386 param.setPartName(partName);
1387 if(paramMode == Mode.INOUT){
1388 ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN);
1389 param.setInBinding(pb);
1390 pb = getBinding(operationName, partName, isHeader, Mode.OUT);
1391 param.setOutBinding(pb);
1392 }else{
1393 if (isHeader){
1394 param.setBinding(ParameterBinding.HEADER);
1395 }else{
1396 ParameterBinding pb = getBinding(operationName, partName, false, paramMode);
1397 param.setBinding(pb);
1398 }
1399 }
1400 javaMethod.addParameter(param);
1401 }
1402 validateDocBare(javaMethod);
1403 processExceptions(javaMethod, method);
1404 }
1406 // Does a conservative check if there is only one BODY part for input
1407 // and output message. We are not considering INOUT parameters at this
1408 // time since binding information is not applied. Also, there isn't
1409 // anyway to represent some cases in SEI. For example, a INOUT parameter
1410 // could be bound to body for input message, header for OUTPUT message
1411 // in wsdl:binding
1412 private void validateDocBare(JavaMethodImpl javaMethod) {
1413 int numInBodyBindings = 0;
1414 for(Parameter param : javaMethod.getRequestParameters()){
1415 if(param.getBinding().equals(ParameterBinding.BODY) && param.isIN()){
1416 numInBodyBindings++;
1417 }
1418 if(numInBodyBindings > 1){
1419 throw new RuntimeModelerException(ModelerMessages.localizableNOT_A_VALID_BARE_METHOD(portClass.getName(), javaMethod.getMethod().getName()));
1420 }
1421 }
1423 int numOutBodyBindings = 0;
1424 for(Parameter param : javaMethod.getResponseParameters()){
1425 if(param.getBinding().equals(ParameterBinding.BODY) && param.isOUT()){
1426 numOutBodyBindings++;
1427 }
1428 if(numOutBodyBindings > 1){
1429 throw new RuntimeModelerException(ModelerMessages.localizableNOT_A_VALID_BARE_METHOD(portClass.getName(), javaMethod.getMethod().getName()));
1430 }
1431 }
1432 }
1434 private Class getAsyncReturnType(Method method, Class returnType) {
1435 if(Response.class.isAssignableFrom(returnType)){
1436 Type ret = method.getGenericReturnType();
1437 return (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)ret).getActualTypeArguments()[0]);
1438 }else{
1439 Type[] types = method.getGenericParameterTypes();
1440 Class[] params = method.getParameterTypes();
1441 int i = 0;
1442 for(Class cls : params){
1443 if(AsyncHandler.class.isAssignableFrom(cls)){
1444 return (Class) Utils.REFLECTION_NAVIGATOR.erasure(((ParameterizedType)types[i]).getActualTypeArguments()[0]);
1445 }
1446 i++;
1447 }
1448 }
1449 return returnType;
1450 }
1452 /**
1453 * utility to capitalize the first letter in a string
1454 * @param name the string to capitalize
1455 * @return the capitalized string
1456 */
1457 public static String capitalize(String name) {
1458 if (name == null || name.length() == 0) {
1459 return name;
1460 }
1461 char chars[] = name.toCharArray();
1462 chars[0] = Character.toUpperCase(chars[0]);
1463 return new String(chars);
1464 }
1466 /*
1467 * Return service QName
1468 */
1469 /**
1470 * gets the <code>wsdl:serviceName</code> for a given implementation class
1471 * @param implClass the implementation class
1472 * @return the <code>wsdl:serviceName</code> for the <code>implClass</code>
1473 */
1474 public static QName getServiceName(Class<?> implClass) {
1475 return getServiceName(implClass, null);
1476 }
1478 public static QName getServiceName(Class<?> implClass, boolean isStandard) {
1479 return getServiceName(implClass, null, isStandard);
1480 }
1482 public static QName getServiceName(Class<?> implClass, MetadataReader reader) {
1483 return getServiceName(implClass, reader, true);
1484 }
1486 public static QName getServiceName(Class<?> implClass, MetadataReader reader, boolean isStandard) {
1487 if (implClass.isInterface()) {
1488 throw new RuntimeModelerException("runtime.modeler.cannot.get.serviceName.from.interface",
1489 implClass.getCanonicalName());
1490 }
1492 String name = implClass.getSimpleName()+SERVICE;
1493 String packageName = "";
1494 if (implClass.getPackage() != null)
1495 packageName = implClass.getPackage().getName();
1497 WebService webService = getAnnotation(WebService.class, implClass, reader);
1498 if (isStandard && webService == null) {
1499 throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1500 implClass.getCanonicalName());
1501 }
1502 if (webService != null && webService.serviceName().length() > 0) {
1503 name = webService.serviceName();
1504 }
1505 String targetNamespace = getNamespace(packageName);
1506 if (webService != null && webService.targetNamespace().length() > 0) {
1507 targetNamespace = webService.targetNamespace();
1508 } else if (targetNamespace == null) {
1509 throw new RuntimeModelerException("runtime.modeler.no.package",
1510 implClass.getName());
1511 }
1512 return new QName(targetNamespace, name);
1513 }
1515 /**
1516 * gets the <code>wsdl:portName</code> for a given implementation class
1517 * @param implClass the implementation class
1518 * @param targetNamespace Namespace URI for service name
1519 * @return the <code>wsdl:portName</code> for the <code>implClass</code>
1520 */
1521 public static QName getPortName(Class<?> implClass, String targetNamespace) {
1522 return getPortName(implClass, null, targetNamespace);
1523 }
1525 public static QName getPortName(Class<?> implClass, String targetNamespace, boolean isStandard) {
1526 return getPortName(implClass, null, targetNamespace, isStandard);
1527 }
1529 public static QName getPortName(Class<?> implClass, MetadataReader reader, String targetNamespace) {
1530 return getPortName(implClass, reader, targetNamespace, true);
1531 }
1533 public static QName getPortName(Class<?> implClass, MetadataReader reader, String targetNamespace, boolean isStandard) {
1534 WebService webService = getAnnotation(WebService.class, implClass, reader);
1535 if (isStandard && webService == null) {
1536 throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1537 implClass.getCanonicalName());
1538 }
1539 String name;
1540 if (webService != null && webService.portName().length() > 0) {
1541 name = webService.portName();
1542 } else if (webService != null && webService.name().length() > 0) {
1543 name = webService.name()+PORT;
1544 } else {
1545 name = implClass.getSimpleName()+PORT;
1546 }
1548 if (targetNamespace == null) {
1549 if (webService != null && webService.targetNamespace().length() > 0) {
1550 targetNamespace = webService.targetNamespace();
1551 } else {
1552 String packageName = null;
1553 if (implClass.getPackage() != null) {
1554 packageName = implClass.getPackage().getName();
1555 }
1556 if (packageName != null) {
1557 targetNamespace = getNamespace(packageName);
1558 }
1559 if (targetNamespace == null) {
1560 throw new RuntimeModelerException("runtime.modeler.no.package",
1561 implClass.getName());
1562 }
1563 }
1565 }
1567 return new QName(targetNamespace, name);
1568 }
1570 static <A extends Annotation> A getAnnotation(Class<A> t, Class<?> cls, MetadataReader reader) {
1571 return (reader == null)? cls.getAnnotation(t) : reader.getAnnotation(t, cls);
1572 }
1574 /**
1575 * Gives portType QName from implementatorClass or SEI
1576 * @param implOrSeiClass cant be null
1577 * @return <code>wsdl:portType@name</code>, null if it could not find the annotated class.
1578 */
1579 public static QName getPortTypeName(Class<?> implOrSeiClass){
1580 return getPortTypeName(implOrSeiClass, null, null);
1581 }
1583 public static QName getPortTypeName(Class<?> implOrSeiClass, MetadataReader metadataReader){
1584 return getPortTypeName(implOrSeiClass, null, metadataReader);
1585 }
1587 public static QName getPortTypeName(Class<?> implOrSeiClass, String tns, MetadataReader reader){
1588 assert(implOrSeiClass != null);
1589 WebService webService = getAnnotation(WebService.class, implOrSeiClass, reader);
1590 Class<?> clazz = implOrSeiClass;
1591 if (webService == null)
1592 throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1593 implOrSeiClass.getCanonicalName());
1595 if (!implOrSeiClass.isInterface()) {
1596 String epi = webService.endpointInterface();
1597 if (epi.length() > 0) {
1598 try {
1599 clazz = Thread.currentThread().getContextClassLoader().loadClass(epi);
1600 } catch (ClassNotFoundException e) {
1601 throw new RuntimeModelerException("runtime.modeler.class.not.found", epi);
1602 }
1603 WebService ws = getAnnotation(WebService.class, clazz, reader);
1604 if (ws == null) {
1605 throw new RuntimeModelerException("runtime.modeler.endpoint.interface.no.webservice",
1606 webService.endpointInterface());
1607 }
1608 }
1609 }
1611 webService = getAnnotation(WebService.class, clazz, reader);
1612 String name = webService.name();
1613 if(name.length() == 0){
1614 name = clazz.getSimpleName();
1615 }
1616 if (tns == null || "".equals(tns.trim())) tns = webService.targetNamespace();
1617 if (tns.length() == 0)
1618 tns = getNamespace(clazz.getPackage().getName());
1619 if (tns == null) {
1620 throw new RuntimeModelerException("runtime.modeler.no.package", clazz.getName());
1621 }
1622 return new QName(tns, name);
1623 }
1625 private ParameterBinding getBinding(String operation, String part, boolean isHeader, Mode mode){
1626 if(binding == null){
1627 if(isHeader)
1628 return ParameterBinding.HEADER;
1629 else
1630 return ParameterBinding.BODY;
1631 }
1632 QName opName = new QName(binding.getBinding().getPortType().getName().getNamespaceURI(), operation);
1633 return binding.getBinding().getBinding(opName, part, mode);
1634 }
1636 private WSDLPart getPart(QName opName, String partName, Mode mode){
1637 if(binding != null){
1638 WSDLBoundOperation bo = binding.getBinding().get(opName);
1639 if(bo != null)
1640 return bo.getPart(partName, mode);
1641 }
1642 return null;
1643 }
1645 private static Boolean getBooleanSystemProperty(final String prop) {
1646 return AccessController.doPrivileged(
1647 new java.security.PrivilegedAction<Boolean>() {
1648 public Boolean run() {
1649 String value = System.getProperty(prop);
1650 return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
1651 }
1652 }
1653 );
1654 }
1656 private static QName getReturnQName(Method method, WebResult webResult, XmlElement xmlElem) {
1657 String webResultName = null;
1658 if (webResult != null && webResult.name().length() > 0) {
1659 webResultName = webResult.name();
1660 }
1661 String xmlElemName = null;
1662 if (xmlElem != null && !xmlElem.name().equals("##default")) {
1663 xmlElemName = xmlElem.name();
1664 }
1665 if (xmlElemName != null && webResultName != null && !xmlElemName.equals(webResultName)) {
1666 throw new RuntimeModelerException("@XmlElement(name)="+xmlElemName+" and @WebResult(name)="+webResultName+" are different for method " +method);
1667 }
1668 String localPart = RETURN;
1669 if (webResultName != null) {
1670 localPart = webResultName;
1671 } else if (xmlElemName != null) {
1672 localPart = xmlElemName;
1673 }
1675 String webResultNS = null;
1676 if (webResult != null && webResult.targetNamespace().length() > 0) {
1677 webResultNS = webResult.targetNamespace();
1678 }
1679 String xmlElemNS = null;
1680 if (xmlElem != null && !xmlElem.namespace().equals("##default")) {
1681 xmlElemNS = xmlElem.namespace();
1682 }
1683 if (xmlElemNS != null && webResultNS != null && !xmlElemNS.equals(webResultNS)) {
1684 throw new RuntimeModelerException("@XmlElement(namespace)="+xmlElemNS+" and @WebResult(targetNamespace)="+webResultNS+" are different for method " +method);
1685 }
1686 String ns = "";
1687 if (webResultNS != null) {
1688 ns = webResultNS;
1689 } else if (xmlElemNS != null) {
1690 ns = xmlElemNS;
1691 }
1693 return new QName(ns, localPart);
1694 }
1696 private static QName getParameterQName(Method method, WebParam webParam, XmlElement xmlElem, String paramDefault) {
1697 String webParamName = null;
1698 if (webParam != null && webParam.name().length() > 0) {
1699 webParamName = webParam.name();
1700 }
1701 String xmlElemName = null;
1702 if (xmlElem != null && !xmlElem.name().equals("##default")) {
1703 xmlElemName = xmlElem.name();
1704 }
1705 if (xmlElemName != null && webParamName != null && !xmlElemName.equals(webParamName)) {
1706 throw new RuntimeModelerException("@XmlElement(name)="+xmlElemName+" and @WebParam(name)="+webParamName+" are different for method " +method);
1707 }
1708 String localPart = paramDefault;
1709 if (webParamName != null) {
1710 localPart = webParamName;
1711 } else if (xmlElemName != null) {
1712 localPart = xmlElemName;
1713 }
1715 String webParamNS = null;
1716 if (webParam != null && webParam.targetNamespace().length() > 0) {
1717 webParamNS = webParam.targetNamespace();
1718 }
1719 String xmlElemNS = null;
1720 if (xmlElem != null && !xmlElem.namespace().equals("##default")) {
1721 xmlElemNS = xmlElem.namespace();
1722 }
1723 if (xmlElemNS != null && webParamNS != null && !xmlElemNS.equals(webParamNS)) {
1724 throw new RuntimeModelerException("@XmlElement(namespace)="+xmlElemNS+" and @WebParam(targetNamespace)="+webParamNS+" are different for method " +method);
1725 }
1726 String ns = "";
1727 if (webParamNS != null) {
1728 ns = webParamNS;
1729 } else if (xmlElemNS != null) {
1730 ns = xmlElemNS;
1731 }
1733 return new QName(ns, localPart);
1734 }
1737 }