Fri, 04 Oct 2013 16:21:34 +0100
8025054: Update JAX-WS RI integration to 2.2.9-b130926.1035
Reviewed-by: chegar
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.BindingHelper;
49 import com.sun.xml.internal.ws.spi.db.TypeInfo;
50 import com.sun.xml.internal.ws.spi.db.WrapperComposite;
52 import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion;
54 import javax.jws.*;
55 import javax.jws.WebParam.Mode;
56 import javax.jws.soap.SOAPBinding;
57 import javax.jws.soap.SOAPBinding.Style;
58 import javax.xml.bind.annotation.XmlElement;
59 import javax.xml.bind.annotation.XmlSeeAlso;
60 import javax.xml.namespace.QName;
61 import javax.xml.ws.*;
62 import javax.xml.ws.soap.MTOM;
63 import javax.xml.ws.soap.MTOMFeature;
64 import java.lang.annotation.Annotation;
65 import java.lang.reflect.Method;
66 import java.lang.reflect.Modifier;
67 import java.lang.reflect.ParameterizedType;
68 import java.lang.reflect.Type;
69 import java.rmi.RemoteException;
70 import java.security.AccessController;
71 import java.util.HashSet;
72 import java.util.Map;
73 import java.util.Set;
74 import java.util.StringTokenizer;
75 import java.util.TreeMap;
76 import java.util.concurrent.Future;
77 import java.util.logging.Logger;
79 import static javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED;
81 /**
82 * Creates a runtime model of a SEI (portClass).
83 *
84 * @author WS Developement Team
85 */
86 public class RuntimeModeler {
87 private final WebServiceFeatureList features;
88 private BindingID bindingId;
89 private WSBinding wsBinding;
90 private final Class portClass;
91 private AbstractSEIModelImpl model;
92 private SOAPBindingImpl defaultBinding;
93 // can be empty but never null
94 private String packageName;
95 private String targetNamespace;
96 private boolean isWrapped = true;
97 private ClassLoader classLoader;
98 private final WSDLPort binding;
99 private QName serviceName;
100 private QName portName;
101 private Set<Class> classUsesWebMethod;
102 private DatabindingConfig config;
103 private MetadataReader metadataReader;
104 /**
105 *
106 */
107 public static final String PD_JAXWS_PACKAGE_PD = ".jaxws.";
108 /**
109 *
110 */
111 public static final String JAXWS_PACKAGE_PD = "jaxws.";
112 public static final String RESPONSE = "Response";
113 public static final String RETURN = "return";
114 public static final String BEAN = "Bean";
115 public static final String SERVICE = "Service";
116 public static final String PORT = "Port";
117 public static final Class HOLDER_CLASS = Holder.class;
118 public static final Class<RemoteException> REMOTE_EXCEPTION_CLASS = RemoteException.class;
119 public static final Class<RuntimeException> RUNTIME_EXCEPTION_CLASS = RuntimeException.class;
120 public static final Class<Exception> EXCEPTION_CLASS = Exception.class;
121 public static final String DecapitalizeExceptionBeanProperties = "com.sun.xml.internal.ws.api.model.DecapitalizeExceptionBeanProperties";
122 public static final String SuppressDocLitWrapperGeneration = "com.sun.xml.internal.ws.api.model.SuppressDocLitWrapperGeneration";
123 public static final String DocWrappeeNamespapceQualified = "com.sun.xml.internal.ws.api.model.DocWrappeeNamespapceQualified";
125 /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull BindingID bindingId, @NotNull WebServiceFeature... features) {
126 this(portClass, serviceName, null, bindingId, features);
127 }*/
129 /**
130 *
131 * creates an instance of RunTimeModeler given a <code>sei</code> and <code>binding</code>
132 * @param portClass The SEI class to be modeled.
133 * @param serviceName The ServiceName to use instead of one calculated from the implementation class
134 * @param wsdlPort {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLPort}
135 * @param features web service features
136 */
137 /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull WSDLPortImpl wsdlPort, @NotNull WebServiceFeature... features){
138 this(portClass, serviceName, wsdlPort, wsdlPort.getBinding().getBindingId(), features);
139 }*/
141 /*private RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, WSDLPortImpl binding, BindingID bindingId, @NotNull WebServiceFeature... features) {
142 this.portClass = portClass;
143 this.serviceName = serviceName;
144 this.binding = binding;
145 this.bindingId = bindingId;
146 this.features = features;
147 }*/
149 public RuntimeModeler(@NotNull DatabindingConfig config){
150 this.portClass = (config.getEndpointClass() != null)? config.getEndpointClass() : config.getContractClass();
151 this.serviceName = config.getMappingInfo().getServiceName();
152 this.binding = config.getWsdlPort();
153 this.classLoader = config.getClassLoader();
154 this.portName = config.getMappingInfo().getPortName();
155 this.config = config;
156 this.wsBinding = config.getWSBinding();
157 metadataReader = config.getMetadataReader();
158 targetNamespace = config.getMappingInfo().getTargetNamespace();
159 if (metadataReader == null) metadataReader = new ReflectAnnotationReader();
160 if (wsBinding != null) {
161 this.bindingId = wsBinding.getBindingId();
162 if (config.getFeatures() != null) wsBinding.getFeatures().mergeFeatures(config.getFeatures(), false);
163 if (binding != null) wsBinding.getFeatures().mergeFeatures(binding.getFeatures(), false);
164 this.features = WebServiceFeatureList.toList(wsBinding.getFeatures());
165 } else {
166 this.bindingId = config.getMappingInfo().getBindingID();
167 this.features = WebServiceFeatureList.toList(config.getFeatures());
168 if (binding != null) bindingId = binding.getBinding().getBindingId();
169 if (bindingId == null) bindingId = getDefaultBindingID();
170 if (!features.contains(MTOMFeature.class)) {
171 MTOM mtomAn = getAnnotation(portClass, MTOM.class);
172 if (mtomAn != null) features.add(WebServiceFeatureList.getFeature(mtomAn));
173 }
174 if (!features.contains(com.oracle.webservices.internal.api.EnvelopeStyleFeature.class)) {
175 com.oracle.webservices.internal.api.EnvelopeStyle es = getAnnotation(portClass, com.oracle.webservices.internal.api.EnvelopeStyle.class);
176 if (es != null) features.add(WebServiceFeatureList.getFeature(es));
177 }
178 this.wsBinding = bindingId.createBinding(features);
179 }
180 }
182 private BindingID getDefaultBindingID() {
183 BindingType bt = getAnnotation(portClass, BindingType.class);
184 if (bt != null) return BindingID.parse(bt.value());
185 SOAPVersion ver = getSoapVersion(features);
186 boolean mtomEnabled = features.isEnabled(MTOMFeature.class);
187 if (SOAPVersion.SOAP_12.equals(ver)) {
188 return (mtomEnabled) ? BindingID.SOAP12_HTTP_MTOM : BindingID.SOAP12_HTTP;
189 } else {
190 return (mtomEnabled) ? BindingID.SOAP11_HTTP_MTOM : BindingID.SOAP11_HTTP;
191 }
192 }
194 /**
195 * sets the classloader to be used when loading classes by the <code>RuntimeModeler</code>.
196 * @param classLoader ClassLoader used to load classes
197 */
198 public void setClassLoader(ClassLoader classLoader) {
199 this.classLoader = classLoader;
200 }
202 /**
203 * sets the PortName to be used by the <code>RuntimeModeler</code>.
204 * @param portName The PortName to be used instead of the PortName
205 * retrieved via annotations
206 */
207 public void setPortName(QName portName) {
208 this.portName = portName;
209 }
211 private <T extends Annotation> T getAnnotation(final Class<?> clazz, final Class<T> T) {
212 return metadataReader.getAnnotation(T, clazz);
213 }
215 private <T extends Annotation> T getAnnotation(final Method method, final Class<T> T) {
216 return metadataReader.getAnnotation(T, method);
217 }
219 private Annotation[] getAnnotations(final Method method) {
220 return metadataReader.getAnnotations(method);
221 }
223 private Annotation[] getAnnotations(final Class<?> c) {
224 return metadataReader.getAnnotations(c);
225 }
226 private Annotation[][] getParamAnnotations(final Method method) {
227 return metadataReader.getParameterAnnotations(method);
228 }
230 private static final Logger logger =
231 Logger.getLogger(
232 com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server");
234 //currently has many local vars which will be eliminated after debugging issues
235 //first draft
236 /**
237 * builds the runtime model from the <code>portClass</code> using the binding ID <code>bindingId</code>.
238 * @return the runtime model for the <code>portClass</code>.
239 */
240 public AbstractSEIModelImpl buildRuntimeModel() {
241 model = new SOAPSEIModel(features);
242 model.contractClass = config.getContractClass();
243 model.endpointClass = config.getEndpointClass();
244 model.classLoader = this.classLoader;
245 model.wsBinding = wsBinding;
246 model.databindingInfo.setWsdlURL(config.getWsdlURL());
247 model.databindingInfo.properties().putAll(config.properties());
248 if (model.contractClass == null) model.contractClass = portClass;
249 if (model.endpointClass == null && !portClass.isInterface()) model.endpointClass = portClass;
250 Class<?> seiClass = portClass;
251 metadataReader.getProperties(model.databindingInfo.properties(), portClass);
252 WebService webService = getAnnotation(portClass, WebService.class);
253 if (webService == null) {
254 throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
255 portClass.getCanonicalName());
256 }
257 Class<?> seiFromConfig = configEndpointInterface();
258 if (webService.endpointInterface().length() > 0 || seiFromConfig != null) {
259 if (seiFromConfig != null) {
260 seiClass = seiFromConfig;
261 } else {
262 seiClass = getClass(webService.endpointInterface(), ModelerMessages.localizableRUNTIME_MODELER_CLASS_NOT_FOUND(webService.endpointInterface()));
263 }
264 model.contractClass = seiClass;
265 model.endpointClass = portClass;
266 WebService seiService = getAnnotation(seiClass, WebService.class);
267 if (seiService == null) {
268 throw new RuntimeModelerException("runtime.modeler.endpoint.interface.no.webservice",
269 webService.endpointInterface());
270 }
272 //check if @SOAPBinding is defined on the impl class
273 SOAPBinding sbPortClass = getAnnotation(portClass, SOAPBinding.class);
274 SOAPBinding sbSei = getAnnotation(seiClass, SOAPBinding.class);
275 if(sbPortClass != null){
276 if(sbSei == null || sbSei.style() != sbPortClass.style()|| sbSei.use() != sbPortClass.use()){
277 logger.warning(ServerMessages.RUNTIMEMODELER_INVALIDANNOTATION_ON_IMPL("@SOAPBinding", portClass.getName(), seiClass.getName()));
278 }
279 }
280 }
281 if (serviceName == null)
282 serviceName = getServiceName(portClass, metadataReader);
283 model.setServiceQName(serviceName);
285 // String portLocalName = portClass.getSimpleName()+PORT;
286 // if (webService.portName().length() >0) {
287 // portLocalName = webService.portName();
288 // } else if (webService.name().length() >0) {
289 // portLocalName = webService.name()+PORT;
290 // }
291 //
292 // if (portName == null)
293 // portName = new QName(serviceName.getNamespaceURI(), portLocalName);
294 // if (!portName.getNamespaceURI().equals(serviceName.getNamespaceURI())) {
295 // throw new RuntimeModelerException("runtime.modeler.portname.servicename.namespace.mismatch",
296 // serviceName, portName);
297 // }
299 if (portName == null) portName = getPortName(portClass, metadataReader, serviceName.getNamespaceURI());
300 model.setPortName(portName);
302 // Check if databinding is overridden in annotation.
303 com.oracle.webservices.internal.api.databinding.DatabindingMode dbm2 = getAnnotation(portClass, com.oracle.webservices.internal.api.databinding.DatabindingMode.class);
304 if (dbm2 != null) model.databindingInfo.setDatabindingMode(dbm2.value());
306 processClass(seiClass);
307 if (model.getJavaMethods().size() == 0)
308 throw new RuntimeModelerException("runtime.modeler.no.operations",
309 portClass.getName());
310 model.postProcess();
312 // Make the configured databinding mode available to the
313 // DatabindingConfig.
314 config.properties().put(BindingContext.class.getName(),
315 model.bindingContext);
317 // TODO: this needs to be fixed properly --
318 // when we are building RuntimeModel first before building WSDLModel,
319 // we still need to do this correctly
320 if(binding!=null)
321 model.freeze(binding);
322 return model;
323 }
325 private Class configEndpointInterface() {
326 if (config.getEndpointClass() == null ||
327 config.getEndpointClass().isInterface() ) return null; //client proxy Interface
328 return config.getContractClass();
329 }
331 /**
332 * utility method to load classes
333 * @param className the name of the class to load
334 * @param errorMessage
335 * Error message to use when the resolution fails.
336 * @return the class specified by <code>className</code>
337 */
338 private Class getClass(String className, Localizable errorMessage) {
339 try {
340 if (classLoader == null)
341 return Thread.currentThread().getContextClassLoader().loadClass(className);
342 else
343 return classLoader.loadClass(className);
344 } catch (ClassNotFoundException e) {
345 throw new RuntimeModelerException(errorMessage);
346 }
347 }
349 private boolean noWrapperGen() {
350 Object o = config.properties().get(SuppressDocLitWrapperGeneration);
351 return (o!= null && o instanceof Boolean) ? ((Boolean) o) : false;
352 }
354 private Class getRequestWrapperClass(String className, Method method, QName reqElemName) {
355 ClassLoader loader = (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader;
356 try {
357 return loader.loadClass(className);
358 } catch (ClassNotFoundException e) {
359 if (noWrapperGen()) return WrapperComposite.class;
360 logger.fine("Dynamically creating request wrapper Class " + className);
361 return WrapperBeanGenerator.createRequestWrapperBean(className, method, reqElemName, loader);
362 }
363 }
365 private Class getResponseWrapperClass(String className, Method method, QName resElemName) {
366 ClassLoader loader = (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader;
367 try {
368 return loader.loadClass(className);
369 } catch (ClassNotFoundException e) {
370 if (noWrapperGen()) return WrapperComposite.class;
371 logger.fine("Dynamically creating response wrapper bean Class " + className);
372 return WrapperBeanGenerator.createResponseWrapperBean(className, method, resElemName, loader);
373 }
374 }
377 private Class getExceptionBeanClass(String className, Class exception, String name, String namespace) {
378 boolean decapitalizeExceptionBeanProperties = true;
379 Object o = config.properties().get(DecapitalizeExceptionBeanProperties);
380 if (o!= null && o instanceof Boolean) decapitalizeExceptionBeanProperties = (Boolean) o;
381 ClassLoader loader = (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader;
382 try {
383 return loader.loadClass(className);
384 } catch (ClassNotFoundException e) {
385 logger.fine("Dynamically creating exception bean Class " + className);
386 return WrapperBeanGenerator.createExceptionBean(className, exception, targetNamespace, name, namespace, loader, decapitalizeExceptionBeanProperties);
387 }
388 }
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 }
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());
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);
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 }*/
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 }
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) {
497 int modifiers = method.getModifiers();
498 boolean staticFinal = Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers);
500 assert Modifier.isPublic(modifiers);
501 assert !clazz.isInterface();
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 }
514 if (staticFinal) {
515 return false;
516 }
518 Class declClass = method.getDeclaringClass();
519 return getAnnotation(declClass, WebService.class) != null;
520 }
522 private boolean isWebMethod(Method method) {
523 int modifiers = method.getModifiers();
524 if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers))
525 return false;
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 }
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 }
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;
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 }
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) || REMOTE_EXCEPTION_CLASS.isAssignableFrom(exception));
589 }
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
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 }
614 if (webMethod != null && webMethod.exclude())
615 return;
616 */
618 String methodName = method.getName();
619 boolean isOneway = (getAnnotation(method, Oneway.class) != null);
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 }
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 }
648 //set MEP -oneway, async, req/resp
649 MEP mep = getMEP(method);
650 javaMethod.setMEP(mep);
652 String action = null;
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 }
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 }
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 }
688 if(methodBinding!= null && defaultBinding.getStyle() != methodBinding.style()) {
689 throw new RuntimeModelerException("runtime.modeler.soapbinding.conflict",
690 methodBinding.style(), method.getName(),defaultBinding.getStyle());
691 }
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 }
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 }
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 }
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 }
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);
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 }
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 }
828 // return value
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 }
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 }
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;
881 if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
882 continue;
883 }
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 = BindingHelper.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 }
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++);
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 }
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 }
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 }
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;
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>();
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;
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 }
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 }
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 }
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 }
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);
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);
1054 if(javaMethod.isAsync()){
1055 returnType = getAsyncReturnType(method, returnType);
1056 }
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 }
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;
1096 if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
1097 continue;
1098 }
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 = BindingHelper.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 }
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 }
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);
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(p.getIndex(), param);
1172 }
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 }
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()) {
1209 //Exclude RuntimeException, RemoteException and Error etc
1210 if (!EXCEPTION_CLASS.isAssignableFrom(exception))
1211 continue;
1212 if (RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || REMOTE_EXCEPTION_CLASS.isAssignableFrom(exception))
1213 continue;
1215 Class exceptionBean;
1216 Annotation[] anns;
1217 WebFault webFault = getAnnotation(exception, WebFault.class);
1218 Method faultInfoMethod = getWSDLExceptionFaultInfo(exception);
1219 ExceptionType exceptionType = ExceptionType.WSDLException;
1220 String namespace = targetNamespace;
1221 String name = exception.getSimpleName();
1222 String beanPackage = packageName + PD_JAXWS_PACKAGE_PD;
1223 if (packageName.length() == 0)
1224 beanPackage = JAXWS_PACKAGE_PD;
1225 String className = beanPackage+ name + BEAN;
1226 String messageName = exception.getSimpleName();
1227 if (webFault != null) {
1228 if (webFault.faultBean().length()>0)
1229 className = webFault.faultBean();
1230 if (webFault.name().length()>0)
1231 name = webFault.name();
1232 if (webFault.targetNamespace().length()>0)
1233 namespace = webFault.targetNamespace();
1234 if (webFault.messageName().length()>0)
1235 messageName = webFault.messageName();
1236 }
1237 if (faultInfoMethod == null) {
1238 exceptionBean = getExceptionBeanClass(className, exception, name, namespace);
1239 exceptionType = ExceptionType.UserDefined;
1240 anns = getAnnotations(exceptionBean);
1241 } else {
1242 exceptionBean = faultInfoMethod.getReturnType();
1243 anns = getAnnotations(faultInfoMethod);
1244 }
1245 QName faultName = new QName(namespace, name);
1246 TypeInfo typeRef = new TypeInfo(faultName, exceptionBean, anns);
1247 CheckedExceptionImpl checkedException =
1248 new CheckedExceptionImpl(javaMethod, exception, typeRef, exceptionType);
1249 checkedException.setMessageName(messageName);
1250 for(FaultAction fa: faultActions) {
1251 if(fa.className().equals(exception) && !fa.value().equals("")) {
1252 checkedException.setFaultAction(fa.value());
1253 break;
1254 }
1255 }
1256 javaMethod.addException(checkedException);
1257 }
1258 }
1260 /**
1261 * returns the method that corresponds to "getFaultInfo". Returns null if this is not an
1262 * exception generated from a WSDL
1263 * @param exception the class to search for the "getFaultInfo" method
1264 * @return the method named "getFaultInfo" if this is an exception generated from WSDL or an
1265 * exception that contains the <code>WebFault</code> annotation. Otherwise it returns null
1266 */
1267 protected Method getWSDLExceptionFaultInfo(Class exception) {
1268 // if (!exception.isAnnotationPresent(WebFault.class))
1269 if (getAnnotation(exception, WebFault.class) == null)
1270 return null;
1271 try {
1272 return exception.getMethod("getFaultInfo");
1273 } catch (NoSuchMethodException e) {
1274 return null;
1275 }
1276 }
1278 /**
1279 * models a document/literal bare method
1280 * @param javaMethod the runtime model <code>JavaMethod</code> instance being created
1281 * @param operationName the runtime model <code>JavaMethod</code> instance being created
1282 * @param method the runtime model <code>JavaMethod</code> instance being created
1283 */
1284 protected void processDocBareMethod(JavaMethodImpl javaMethod,
1285 String operationName, Method method) {
1287 String resultName = operationName+RESPONSE;
1288 String resultTNS = targetNamespace;
1289 String resultPartName = null;
1290 boolean isResultHeader = false;
1291 WebResult webResult = getAnnotation(method, WebResult.class);
1292 if (webResult != null) {
1293 if (webResult.name().length() > 0)
1294 resultName = webResult.name();
1295 if (webResult.targetNamespace().length() > 0)
1296 resultTNS = webResult.targetNamespace();
1297 resultPartName = webResult.partName();
1298 isResultHeader = webResult.header();
1299 }
1301 Class returnType = method.getReturnType();
1302 Type gReturnType = method.getGenericReturnType();
1303 if(javaMethod.isAsync()){
1304 returnType = getAsyncReturnType(method, returnType);
1305 }
1307 if ((returnType != null) && (!returnType.getName().equals("void"))) {
1308 Annotation[] rann = getAnnotations(method);
1309 if (resultName != null) {
1310 QName responseQName = new QName(resultTNS, resultName);
1311 TypeInfo rTypeReference = new TypeInfo(responseQName, returnType, rann);
1312 rTypeReference.setGenericType(gReturnType);
1313 metadataReader.getProperties(rTypeReference.properties(), method);
1314 ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1);
1316 if(resultPartName == null || (resultPartName.length() == 0)){
1317 resultPartName = resultName;
1318 }
1319 returnParameter.setPartName(resultPartName);
1320 if(isResultHeader){
1321 returnParameter.setBinding(ParameterBinding.HEADER);
1322 }else{
1323 ParameterBinding rb = getBinding(operationName, resultPartName, false, Mode.OUT);
1324 returnParameter.setBinding(rb);
1325 }
1326 javaMethod.addParameter(returnParameter);
1327 }
1328 }
1330 //get WebParam
1331 Class<?>[] parameterTypes = method.getParameterTypes();
1332 Type[] genericParameterTypes = method.getGenericParameterTypes();
1333 Annotation[][] pannotations = getParamAnnotations(method);
1334 int pos = 0;
1335 for (Class clazzType : parameterTypes) {
1336 String paramName = operationName; //method.getName();
1337 String partName = null;
1338 String requestNamespace = targetNamespace;
1339 boolean isHeader = false;
1341 //async
1342 if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){
1343 continue;
1344 }
1346 boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType);
1347 //set the actual type argument of Holder in the TypeReference
1348 if (isHolder) {
1349 if (clazzType==Holder.class)
1350 clazzType = BindingHelper.erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]);
1351 }
1353 Mode paramMode = isHolder ? Mode.INOUT : Mode.IN;
1354 for (Annotation annotation : pannotations[pos]) {
1355 if (annotation.annotationType() == javax.jws.WebParam.class) {
1356 javax.jws.WebParam webParam = (javax.jws.WebParam) annotation;
1357 paramMode = webParam.mode();
1358 if (isHolder && paramMode == Mode.IN)
1359 paramMode = Mode.INOUT;
1360 isHeader = webParam.header();
1361 if(isHeader)
1362 paramName = "arg"+pos;
1363 if(paramMode == Mode.OUT && !isHeader)
1364 paramName = operationName+RESPONSE;
1365 if (webParam.name().length() > 0)
1366 paramName = webParam.name();
1367 partName = webParam.partName();
1368 if (!webParam.targetNamespace().equals("")) {
1369 requestNamespace = webParam.targetNamespace();
1370 }
1371 break;
1372 }
1373 }
1375 QName requestQName = new QName(requestNamespace, paramName);
1376 if (!isHeader && paramMode != Mode.OUT) javaMethod.setRequestPayloadName(requestQName);
1377 //doclit/wrapped
1378 TypeInfo typeRef = //operationName with upper 1 char
1379 new TypeInfo(requestQName, clazzType,
1380 pannotations[pos]);
1381 metadataReader.getProperties(typeRef.properties(), method, pos);
1382 typeRef.setGenericType(genericParameterTypes[pos]);
1383 ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++);
1384 if(partName == null || (partName.length() == 0)){
1385 partName = paramName;
1386 }
1387 param.setPartName(partName);
1388 if(paramMode == Mode.INOUT){
1389 ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN);
1390 param.setInBinding(pb);
1391 pb = getBinding(operationName, partName, isHeader, Mode.OUT);
1392 param.setOutBinding(pb);
1393 }else{
1394 if (isHeader){
1395 param.setBinding(ParameterBinding.HEADER);
1396 }else{
1397 ParameterBinding pb = getBinding(operationName, partName, false, paramMode);
1398 param.setBinding(pb);
1399 }
1400 }
1401 javaMethod.addParameter(param);
1402 }
1403 validateDocBare(javaMethod);
1404 processExceptions(javaMethod, method);
1405 }
1407 // Does a conservative check if there is only one BODY part for input
1408 // and output message. We are not considering INOUT parameters at this
1409 // time since binding information is not applied. Also, there isn't
1410 // anyway to represent some cases in SEI. For example, a INOUT parameter
1411 // could be bound to body for input message, header for OUTPUT message
1412 // in wsdl:binding
1413 private void validateDocBare(JavaMethodImpl javaMethod) {
1414 int numInBodyBindings = 0;
1415 for(Parameter param : javaMethod.getRequestParameters()){
1416 if(param.getBinding().equals(ParameterBinding.BODY) && param.isIN()){
1417 numInBodyBindings++;
1418 }
1419 if(numInBodyBindings > 1){
1420 throw new RuntimeModelerException(ModelerMessages.localizableNOT_A_VALID_BARE_METHOD(portClass.getName(), javaMethod.getMethod().getName()));
1421 }
1422 }
1424 int numOutBodyBindings = 0;
1425 for(Parameter param : javaMethod.getResponseParameters()){
1426 if(param.getBinding().equals(ParameterBinding.BODY) && param.isOUT()){
1427 numOutBodyBindings++;
1428 }
1429 if(numOutBodyBindings > 1){
1430 throw new RuntimeModelerException(ModelerMessages.localizableNOT_A_VALID_BARE_METHOD(portClass.getName(), javaMethod.getMethod().getName()));
1431 }
1432 }
1433 }
1435 private Class getAsyncReturnType(Method method, Class returnType) {
1436 if(Response.class.isAssignableFrom(returnType)){
1437 Type ret = method.getGenericReturnType();
1438 return BindingHelper.erasure(((ParameterizedType)ret).getActualTypeArguments()[0]);
1439 }else{
1440 Type[] types = method.getGenericParameterTypes();
1441 Class[] params = method.getParameterTypes();
1442 int i = 0;
1443 for(Class cls : params){
1444 if(AsyncHandler.class.isAssignableFrom(cls)){
1445 return BindingHelper.erasure(((ParameterizedType)types[i]).getActualTypeArguments()[0]);
1446 }
1447 i++;
1448 }
1449 }
1450 return returnType;
1451 }
1453 /**
1454 * utility to capitalize the first letter in a string
1455 * @param name the string to capitalize
1456 * @return the capitalized string
1457 */
1458 public static String capitalize(String name) {
1459 if (name == null || name.length() == 0) {
1460 return name;
1461 }
1462 char chars[] = name.toCharArray();
1463 chars[0] = Character.toUpperCase(chars[0]);
1464 return new String(chars);
1465 }
1467 /*
1468 * Return service QName
1469 */
1470 /**
1471 * gets the <code>wsdl:serviceName</code> for a given implementation class
1472 * @param implClass the implementation class
1473 * @return the <code>wsdl:serviceName</code> for the <code>implClass</code>
1474 */
1475 public static QName getServiceName(Class<?> implClass) {
1476 return getServiceName(implClass, null);
1477 }
1479 public static QName getServiceName(Class<?> implClass, boolean isStandard) {
1480 return getServiceName(implClass, null, isStandard);
1481 }
1483 public static QName getServiceName(Class<?> implClass, MetadataReader reader) {
1484 return getServiceName(implClass, reader, true);
1485 }
1487 public static QName getServiceName(Class<?> implClass, MetadataReader reader, boolean isStandard) {
1488 if (implClass.isInterface()) {
1489 throw new RuntimeModelerException("runtime.modeler.cannot.get.serviceName.from.interface",
1490 implClass.getCanonicalName());
1491 }
1493 String name = implClass.getSimpleName()+SERVICE;
1494 String packageName = "";
1495 if (implClass.getPackage() != null)
1496 packageName = implClass.getPackage().getName();
1498 WebService webService = getAnnotation(WebService.class, implClass, reader);
1499 if (isStandard && webService == null) {
1500 throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1501 implClass.getCanonicalName());
1502 }
1503 if (webService != null && webService.serviceName().length() > 0) {
1504 name = webService.serviceName();
1505 }
1506 String targetNamespace = getNamespace(packageName);
1507 if (webService != null && webService.targetNamespace().length() > 0) {
1508 targetNamespace = webService.targetNamespace();
1509 } else if (targetNamespace == null) {
1510 throw new RuntimeModelerException("runtime.modeler.no.package",
1511 implClass.getName());
1512 }
1513 return new QName(targetNamespace, name);
1514 }
1516 /**
1517 * gets the <code>wsdl:portName</code> for a given implementation class
1518 * @param implClass the implementation class
1519 * @param targetNamespace Namespace URI for service name
1520 * @return the <code>wsdl:portName</code> for the <code>implClass</code>
1521 */
1522 public static QName getPortName(Class<?> implClass, String targetNamespace) {
1523 return getPortName(implClass, null, targetNamespace);
1524 }
1526 public static QName getPortName(Class<?> implClass, String targetNamespace, boolean isStandard) {
1527 return getPortName(implClass, null, targetNamespace, isStandard);
1528 }
1530 public static QName getPortName(Class<?> implClass, MetadataReader reader, String targetNamespace) {
1531 return getPortName(implClass, reader, targetNamespace, true);
1532 }
1534 public static QName getPortName(Class<?> implClass, MetadataReader reader, String targetNamespace, boolean isStandard) {
1535 WebService webService = getAnnotation(WebService.class, implClass, reader);
1536 if (isStandard && webService == null) {
1537 throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1538 implClass.getCanonicalName());
1539 }
1540 String name;
1541 if (webService != null && webService.portName().length() > 0) {
1542 name = webService.portName();
1543 } else if (webService != null && webService.name().length() > 0) {
1544 name = webService.name()+PORT;
1545 } else {
1546 name = implClass.getSimpleName()+PORT;
1547 }
1549 if (targetNamespace == null) {
1550 if (webService != null && webService.targetNamespace().length() > 0) {
1551 targetNamespace = webService.targetNamespace();
1552 } else {
1553 String packageName = null;
1554 if (implClass.getPackage() != null) {
1555 packageName = implClass.getPackage().getName();
1556 }
1557 if (packageName != null) {
1558 targetNamespace = getNamespace(packageName);
1559 }
1560 if (targetNamespace == null) {
1561 throw new RuntimeModelerException("runtime.modeler.no.package",
1562 implClass.getName());
1563 }
1564 }
1566 }
1568 return new QName(targetNamespace, name);
1569 }
1571 static <A extends Annotation> A getAnnotation(Class<A> t, Class<?> cls, MetadataReader reader) {
1572 return (reader == null)? cls.getAnnotation(t) : reader.getAnnotation(t, cls);
1573 }
1575 /**
1576 * Gives portType QName from implementatorClass or SEI
1577 * @param implOrSeiClass cant be null
1578 * @return <code>wsdl:portType@name</code>, null if it could not find the annotated class.
1579 */
1580 public static QName getPortTypeName(Class<?> implOrSeiClass){
1581 return getPortTypeName(implOrSeiClass, null, null);
1582 }
1584 public static QName getPortTypeName(Class<?> implOrSeiClass, MetadataReader metadataReader){
1585 return getPortTypeName(implOrSeiClass, null, metadataReader);
1586 }
1588 public static QName getPortTypeName(Class<?> implOrSeiClass, String tns, MetadataReader reader){
1589 assert(implOrSeiClass != null);
1590 WebService webService = getAnnotation(WebService.class, implOrSeiClass, reader);
1591 Class<?> clazz = implOrSeiClass;
1592 if (webService == null)
1593 throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation",
1594 implOrSeiClass.getCanonicalName());
1596 if (!implOrSeiClass.isInterface()) {
1597 String epi = webService.endpointInterface();
1598 if (epi.length() > 0) {
1599 try {
1600 clazz = Thread.currentThread().getContextClassLoader().loadClass(epi);
1601 } catch (ClassNotFoundException e) {
1602 throw new RuntimeModelerException("runtime.modeler.class.not.found", epi);
1603 }
1604 WebService ws = getAnnotation(WebService.class, clazz, reader);
1605 if (ws == null) {
1606 throw new RuntimeModelerException("runtime.modeler.endpoint.interface.no.webservice",
1607 webService.endpointInterface());
1608 }
1609 }
1610 }
1612 webService = getAnnotation(WebService.class, clazz, reader);
1613 String name = webService.name();
1614 if(name.length() == 0){
1615 name = clazz.getSimpleName();
1616 }
1617 if (tns == null || "".equals(tns.trim())) tns = webService.targetNamespace();
1618 if (tns.length() == 0)
1619 tns = getNamespace(clazz.getPackage().getName());
1620 if (tns == null) {
1621 throw new RuntimeModelerException("runtime.modeler.no.package", clazz.getName());
1622 }
1623 return new QName(tns, name);
1624 }
1626 private ParameterBinding getBinding(String operation, String part, boolean isHeader, Mode mode){
1627 if(binding == null){
1628 if(isHeader)
1629 return ParameterBinding.HEADER;
1630 else
1631 return ParameterBinding.BODY;
1632 }
1633 QName opName = new QName(binding.getBinding().getPortType().getName().getNamespaceURI(), operation);
1634 return binding.getBinding().getBinding(opName, part, mode);
1635 }
1637 private WSDLPart getPart(QName opName, String partName, Mode mode){
1638 if(binding != null){
1639 WSDLBoundOperation bo = binding.getBinding().get(opName);
1640 if(bo != null)
1641 return bo.getPart(partName, mode);
1642 }
1643 return null;
1644 }
1646 private static Boolean getBooleanSystemProperty(final String prop) {
1647 return AccessController.doPrivileged(
1648 new java.security.PrivilegedAction<Boolean>() {
1649 public Boolean run() {
1650 String value = System.getProperty(prop);
1651 return value != null ? Boolean.valueOf(value) : Boolean.FALSE;
1652 }
1653 }
1654 );
1655 }
1657 private static QName getReturnQName(Method method, WebResult webResult, XmlElement xmlElem) {
1658 String webResultName = null;
1659 if (webResult != null && webResult.name().length() > 0) {
1660 webResultName = webResult.name();
1661 }
1662 String xmlElemName = null;
1663 if (xmlElem != null && !xmlElem.name().equals("##default")) {
1664 xmlElemName = xmlElem.name();
1665 }
1666 if (xmlElemName != null && webResultName != null && !xmlElemName.equals(webResultName)) {
1667 throw new RuntimeModelerException("@XmlElement(name)="+xmlElemName+" and @WebResult(name)="+webResultName+" are different for method " +method);
1668 }
1669 String localPart = RETURN;
1670 if (webResultName != null) {
1671 localPart = webResultName;
1672 } else if (xmlElemName != null) {
1673 localPart = xmlElemName;
1674 }
1676 String webResultNS = null;
1677 if (webResult != null && webResult.targetNamespace().length() > 0) {
1678 webResultNS = webResult.targetNamespace();
1679 }
1680 String xmlElemNS = null;
1681 if (xmlElem != null && !xmlElem.namespace().equals("##default")) {
1682 xmlElemNS = xmlElem.namespace();
1683 }
1684 if (xmlElemNS != null && webResultNS != null && !xmlElemNS.equals(webResultNS)) {
1685 throw new RuntimeModelerException("@XmlElement(namespace)="+xmlElemNS+" and @WebResult(targetNamespace)="+webResultNS+" are different for method " +method);
1686 }
1687 String ns = "";
1688 if (webResultNS != null) {
1689 ns = webResultNS;
1690 } else if (xmlElemNS != null) {
1691 ns = xmlElemNS;
1692 }
1694 return new QName(ns, localPart);
1695 }
1697 private static QName getParameterQName(Method method, WebParam webParam, XmlElement xmlElem, String paramDefault) {
1698 String webParamName = null;
1699 if (webParam != null && webParam.name().length() > 0) {
1700 webParamName = webParam.name();
1701 }
1702 String xmlElemName = null;
1703 if (xmlElem != null && !xmlElem.name().equals("##default")) {
1704 xmlElemName = xmlElem.name();
1705 }
1706 if (xmlElemName != null && webParamName != null && !xmlElemName.equals(webParamName)) {
1707 throw new RuntimeModelerException("@XmlElement(name)="+xmlElemName+" and @WebParam(name)="+webParamName+" are different for method " +method);
1708 }
1709 String localPart = paramDefault;
1710 if (webParamName != null) {
1711 localPart = webParamName;
1712 } else if (xmlElemName != null) {
1713 localPart = xmlElemName;
1714 }
1716 String webParamNS = null;
1717 if (webParam != null && webParam.targetNamespace().length() > 0) {
1718 webParamNS = webParam.targetNamespace();
1719 }
1720 String xmlElemNS = null;
1721 if (xmlElem != null && !xmlElem.namespace().equals("##default")) {
1722 xmlElemNS = xmlElem.namespace();
1723 }
1724 if (xmlElemNS != null && webParamNS != null && !xmlElemNS.equals(webParamNS)) {
1725 throw new RuntimeModelerException("@XmlElement(namespace)="+xmlElemNS+" and @WebParam(targetNamespace)="+webParamNS+" are different for method " +method);
1726 }
1727 String ns = "";
1728 if (webParamNS != null) {
1729 ns = webParamNS;
1730 } else if (xmlElemNS != null) {
1731 ns = xmlElemNS;
1732 }
1734 return new QName(ns, localPart);
1735 }
1738 }