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