/* * Copyright (c) 1997, 2017, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package com.sun.xml.internal.ws.model; import com.sun.istack.internal.NotNull; import com.sun.istack.internal.localization.Localizable; import com.sun.xml.internal.ws.api.BindingID; import com.sun.xml.internal.ws.api.SOAPVersion; import com.sun.xml.internal.ws.api.WSBinding; import com.sun.xml.internal.ws.api.databinding.DatabindingConfig; import com.sun.xml.internal.ws.api.databinding.MetadataReader; import com.sun.xml.internal.ws.api.model.ExceptionType; import com.sun.xml.internal.ws.api.model.MEP; import com.sun.xml.internal.ws.api.model.Parameter; import com.sun.xml.internal.ws.api.model.ParameterBinding; import com.sun.xml.internal.ws.api.model.wsdl.WSDLBoundOperation; import com.sun.xml.internal.ws.api.model.wsdl.WSDLInput; import com.sun.xml.internal.ws.api.model.wsdl.WSDLPart; import com.sun.xml.internal.ws.api.model.wsdl.WSDLPort; import com.sun.xml.internal.ws.binding.WebServiceFeatureList; import com.sun.xml.internal.ws.model.soap.SOAPBindingImpl; import com.sun.xml.internal.ws.resources.ModelerMessages; import com.sun.xml.internal.ws.resources.ServerMessages; import com.sun.xml.internal.ws.spi.db.BindingContext; import com.sun.xml.internal.ws.spi.db.TypeInfo; import com.sun.xml.internal.ws.spi.db.WrapperComposite; import static com.sun.xml.internal.ws.binding.WebServiceFeatureList.getSoapVersion; import static com.sun.xml.internal.ws.model.Utils.REFLECTION_NAVIGATOR; import javax.jws.*; import javax.jws.WebParam.Mode; import javax.jws.soap.SOAPBinding; import javax.jws.soap.SOAPBinding.Style; import javax.xml.bind.annotation.XmlElement; import javax.xml.bind.annotation.XmlSeeAlso; import javax.xml.namespace.QName; import javax.xml.ws.*; import javax.xml.ws.soap.MTOM; import javax.xml.ws.soap.MTOMFeature; import java.lang.annotation.Annotation; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.security.AccessController; import java.util.HashSet; import java.util.Map; import java.util.Set; import java.util.StringTokenizer; import java.util.TreeMap; import java.util.concurrent.Future; import java.util.logging.Logger; import static javax.jws.soap.SOAPBinding.ParameterStyle.WRAPPED; /** * Creates a runtime model of a SEI (portClass). * * @author WS Developement Team */ public class RuntimeModeler { private final WebServiceFeatureList features; private BindingID bindingId; private WSBinding wsBinding; private final Class portClass; private AbstractSEIModelImpl model; private SOAPBindingImpl defaultBinding; // can be empty but never null private String packageName; private String targetNamespace; private boolean isWrapped = true; private ClassLoader classLoader; private final WSDLPort binding; private QName serviceName; private QName portName; private Set classUsesWebMethod; private DatabindingConfig config; private MetadataReader metadataReader; /** * */ public static final String PD_JAXWS_PACKAGE_PD = ".jaxws."; /** * */ public static final String JAXWS_PACKAGE_PD = "jaxws."; public static final String RESPONSE = "Response"; public static final String RETURN = "return"; public static final String BEAN = "Bean"; public static final String SERVICE = "Service"; public static final String PORT = "Port"; public static final Class HOLDER_CLASS = Holder.class; public static final String REMOTE_EXCEPTION_CLASS = "java.rmi.RemoteException"; public static final Class RUNTIME_EXCEPTION_CLASS = RuntimeException.class; public static final Class EXCEPTION_CLASS = Exception.class; public static final String DecapitalizeExceptionBeanProperties = "com.sun.xml.internal.ws.api.model.DecapitalizeExceptionBeanProperties"; public static final String SuppressDocLitWrapperGeneration = "com.sun.xml.internal.ws.api.model.SuppressDocLitWrapperGeneration"; public static final String DocWrappeeNamespapceQualified = "com.sun.xml.internal.ws.api.model.DocWrappeeNamespapceQualified"; /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull BindingID bindingId, @NotNull WebServiceFeature... features) { this(portClass, serviceName, null, bindingId, features); }*/ /** * * creates an instance of RunTimeModeler given a sei and binding * @param portClass The SEI class to be modeled. * @param serviceName The ServiceName to use instead of one calculated from the implementation class * @param wsdlPort {@link com.sun.xml.internal.ws.api.model.wsdl.WSDLPort} * @param features web service features */ /*public RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, @NotNull WSDLPortImpl wsdlPort, @NotNull WebServiceFeature... features){ this(portClass, serviceName, wsdlPort, wsdlPort.getBinding().getBindingId(), features); }*/ /*private RuntimeModeler(@NotNull Class portClass, @NotNull QName serviceName, WSDLPortImpl binding, BindingID bindingId, @NotNull WebServiceFeature... features) { this.portClass = portClass; this.serviceName = serviceName; this.binding = binding; this.bindingId = bindingId; this.features = features; }*/ public RuntimeModeler(@NotNull DatabindingConfig config){ this.portClass = (config.getEndpointClass() != null)? config.getEndpointClass() : config.getContractClass(); this.serviceName = config.getMappingInfo().getServiceName(); this.binding = config.getWsdlPort(); this.classLoader = config.getClassLoader(); this.portName = config.getMappingInfo().getPortName(); this.config = config; this.wsBinding = config.getWSBinding(); metadataReader = config.getMetadataReader(); targetNamespace = config.getMappingInfo().getTargetNamespace(); if (metadataReader == null) metadataReader = new ReflectAnnotationReader(); if (wsBinding != null) { this.bindingId = wsBinding.getBindingId(); if (config.getFeatures() != null) wsBinding.getFeatures().mergeFeatures(config.getFeatures(), false); if (binding != null) wsBinding.getFeatures().mergeFeatures(binding.getFeatures(), false); this.features = WebServiceFeatureList.toList(wsBinding.getFeatures()); } else { this.bindingId = config.getMappingInfo().getBindingID(); this.features = WebServiceFeatureList.toList(config.getFeatures()); if (binding != null) bindingId = binding.getBinding().getBindingId(); if (bindingId == null) bindingId = getDefaultBindingID(); if (!features.contains(MTOMFeature.class)) { MTOM mtomAn = getAnnotation(portClass, MTOM.class); if (mtomAn != null) features.add(WebServiceFeatureList.getFeature(mtomAn)); } if (!features.contains(com.oracle.webservices.internal.api.EnvelopeStyleFeature.class)) { com.oracle.webservices.internal.api.EnvelopeStyle es = getAnnotation(portClass, com.oracle.webservices.internal.api.EnvelopeStyle.class); if (es != null) features.add(WebServiceFeatureList.getFeature(es)); } this.wsBinding = bindingId.createBinding(features); } } private BindingID getDefaultBindingID() { BindingType bt = getAnnotation(portClass, BindingType.class); if (bt != null) return BindingID.parse(bt.value()); SOAPVersion ver = getSoapVersion(features); boolean mtomEnabled = features.isEnabled(MTOMFeature.class); if (SOAPVersion.SOAP_12.equals(ver)) { return (mtomEnabled) ? BindingID.SOAP12_HTTP_MTOM : BindingID.SOAP12_HTTP; } else { return (mtomEnabled) ? BindingID.SOAP11_HTTP_MTOM : BindingID.SOAP11_HTTP; } } /** * sets the classloader to be used when loading classes by the RuntimeModeler. * @param classLoader ClassLoader used to load classes */ public void setClassLoader(ClassLoader classLoader) { this.classLoader = classLoader; } /** * sets the PortName to be used by the RuntimeModeler. * @param portName The PortName to be used instead of the PortName * retrieved via annotations */ public void setPortName(QName portName) { this.portName = portName; } private T getAnnotation(final Class clazz, final Class T) { return metadataReader.getAnnotation(T, clazz); } private T getAnnotation(final Method method, final Class T) { return metadataReader.getAnnotation(T, method); } private Annotation[] getAnnotations(final Method method) { return metadataReader.getAnnotations(method); } private Annotation[] getAnnotations(final Class c) { return metadataReader.getAnnotations(c); } private Annotation[][] getParamAnnotations(final Method method) { return metadataReader.getParameterAnnotations(method); } private static final Logger logger = Logger.getLogger( com.sun.xml.internal.ws.util.Constants.LoggingDomain + ".server"); //currently has many local vars which will be eliminated after debugging issues //first draft /** * builds the runtime model from the portClass using the binding ID bindingId. * @return the runtime model for the portClass. */ public AbstractSEIModelImpl buildRuntimeModel() { model = new SOAPSEIModel(features); model.contractClass = config.getContractClass(); model.endpointClass = config.getEndpointClass(); model.classLoader = this.classLoader; model.wsBinding = wsBinding; model.databindingInfo.setWsdlURL(config.getWsdlURL()); model.databindingInfo.properties().putAll(config.properties()); if (model.contractClass == null) model.contractClass = portClass; if (model.endpointClass == null && !portClass.isInterface()) model.endpointClass = portClass; Class seiClass = portClass; metadataReader.getProperties(model.databindingInfo.properties(), portClass); WebService webService = getAnnotation(portClass, WebService.class); if (webService == null) { throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation", portClass.getCanonicalName()); } Class seiFromConfig = configEndpointInterface(); if (webService.endpointInterface().length() > 0 || seiFromConfig != null) { if (seiFromConfig != null) { seiClass = seiFromConfig; } else { seiClass = getClass(webService.endpointInterface(), ModelerMessages.localizableRUNTIME_MODELER_CLASS_NOT_FOUND(webService.endpointInterface())); } model.contractClass = seiClass; model.endpointClass = portClass; WebService seiService = getAnnotation(seiClass, WebService.class); if (seiService == null) { throw new RuntimeModelerException("runtime.modeler.endpoint.interface.no.webservice", webService.endpointInterface()); } //check if @SOAPBinding is defined on the impl class SOAPBinding sbPortClass = getAnnotation(portClass, SOAPBinding.class); SOAPBinding sbSei = getAnnotation(seiClass, SOAPBinding.class); if(sbPortClass != null){ if(sbSei == null || sbSei.style() != sbPortClass.style()|| sbSei.use() != sbPortClass.use()){ logger.warning(ServerMessages.RUNTIMEMODELER_INVALIDANNOTATION_ON_IMPL("@SOAPBinding", portClass.getName(), seiClass.getName())); } } } if (serviceName == null) serviceName = getServiceName(portClass, metadataReader); model.setServiceQName(serviceName); // String portLocalName = portClass.getSimpleName()+PORT; // if (webService.portName().length() >0) { // portLocalName = webService.portName(); // } else if (webService.name().length() >0) { // portLocalName = webService.name()+PORT; // } // // if (portName == null) // portName = new QName(serviceName.getNamespaceURI(), portLocalName); // if (!portName.getNamespaceURI().equals(serviceName.getNamespaceURI())) { // throw new RuntimeModelerException("runtime.modeler.portname.servicename.namespace.mismatch", // serviceName, portName); // } if (portName == null) portName = getPortName(portClass, metadataReader, serviceName.getNamespaceURI()); model.setPortName(portName); // Check if databinding is overridden in annotation. com.oracle.webservices.internal.api.databinding.DatabindingMode dbm2 = getAnnotation(portClass, com.oracle.webservices.internal.api.databinding.DatabindingMode.class); if (dbm2 != null) model.databindingInfo.setDatabindingMode(dbm2.value()); processClass(seiClass); if (model.getJavaMethods().size() == 0) throw new RuntimeModelerException("runtime.modeler.no.operations", portClass.getName()); model.postProcess(); // Make the configured databinding mode available to the // DatabindingConfig. config.properties().put(BindingContext.class.getName(), model.bindingContext); // TODO: this needs to be fixed properly -- // when we are building RuntimeModel first before building WSDLModel, // we still need to do this correctly if(binding!=null) model.freeze(binding); return model; } private Class configEndpointInterface() { if (config.getEndpointClass() == null || config.getEndpointClass().isInterface() ) return null; //client proxy Interface return config.getContractClass(); } /** * utility method to load classes * @param className the name of the class to load * @param errorMessage * Error message to use when the resolution fails. * @return the class specified by className */ private Class getClass(String className, Localizable errorMessage) { try { if (classLoader == null) return Thread.currentThread().getContextClassLoader().loadClass(className); else return classLoader.loadClass(className); } catch (ClassNotFoundException e) { throw new RuntimeModelerException(errorMessage); } } private boolean noWrapperGen() { Object o = config.properties().get(SuppressDocLitWrapperGeneration); return (o!= null && o instanceof Boolean) ? ((Boolean) o) : false; } private Class getRequestWrapperClass(String className, Method method, QName reqElemName) { ClassLoader loader = (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader; try { return loader.loadClass(className); } catch (ClassNotFoundException e) { if (noWrapperGen()) return WrapperComposite.class; logger.fine("Dynamically creating request wrapper Class " + className); return WrapperBeanGenerator.createRequestWrapperBean(className, method, reqElemName, loader); } } private Class getResponseWrapperClass(String className, Method method, QName resElemName) { ClassLoader loader = (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader; try { return loader.loadClass(className); } catch (ClassNotFoundException e) { if (noWrapperGen()) return WrapperComposite.class; logger.fine("Dynamically creating response wrapper bean Class " + className); return WrapperBeanGenerator.createResponseWrapperBean(className, method, resElemName, loader); } } private Class getExceptionBeanClass(String className, Class exception, String name, String namespace) { boolean decapitalizeExceptionBeanProperties = true; Object o = config.properties().get(DecapitalizeExceptionBeanProperties); if (o!= null && o instanceof Boolean) decapitalizeExceptionBeanProperties = (Boolean) o; ClassLoader loader = (classLoader == null) ? Thread.currentThread().getContextClassLoader() : classLoader; try { return loader.loadClass(className); } catch (ClassNotFoundException e) { if (noWrapperGen()) return exception; logger.fine("Dynamically creating exception bean Class " + className); return WrapperBeanGenerator.createExceptionBean(className, exception, targetNamespace, name, namespace, loader, decapitalizeExceptionBeanProperties); } } protected void determineWebMethodUse(Class clazz) { if (clazz == null) return; if (!clazz.isInterface()) { if (clazz == Object.class) return; WebMethod webMethod; for (Method method : clazz.getMethods()) { if (method.getDeclaringClass()!=clazz) continue; webMethod = getAnnotation(method, WebMethod.class); if (webMethod != null && !webMethod.exclude()) { classUsesWebMethod.add(clazz); break; } } } determineWebMethodUse(clazz.getSuperclass()); } void processClass(Class clazz) { classUsesWebMethod = new HashSet(); determineWebMethodUse(clazz); WebService webService = getAnnotation(clazz, WebService.class); QName portTypeName = getPortTypeName(clazz, targetNamespace, metadataReader); // String portTypeLocalName = clazz.getSimpleName(); // if (webService.name().length() >0) // portTypeLocalName = webService.name(); // // targetNamespace = webService.targetNamespace(); packageName = ""; if (clazz.getPackage() != null) packageName = clazz.getPackage().getName(); // if (targetNamespace.length() == 0) { // targetNamespace = getNamespace(packageName); // } // model.setTargetNamespace(targetNamespace); // QName portTypeName = new QName(targetNamespace, portTypeLocalName); targetNamespace = portTypeName.getNamespaceURI(); model.setPortTypeName(portTypeName); model.setTargetNamespace(targetNamespace); model.defaultSchemaNamespaceSuffix = config.getMappingInfo().getDefaultSchemaNamespaceSuffix(); model.setWSDLLocation(webService.wsdlLocation()); SOAPBinding soapBinding = getAnnotation(clazz, SOAPBinding.class); if (soapBinding != null) { if (soapBinding.style() == SOAPBinding.Style.RPC && soapBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) { throw new RuntimeModelerException("runtime.modeler.invalid.soapbinding.parameterstyle", soapBinding, clazz); } isWrapped = soapBinding.parameterStyle()== WRAPPED; } defaultBinding = createBinding(soapBinding); /* * if clazz != portClass then there is an SEI. If there is an * SEI, then all methods should be processed. However, if there is * no SEI, and the implementation class uses at least one * WebMethod annotation, then only methods with this annotation * will be processed. */ /* if (clazz == portClass) { WebMethod webMethod; for (Method method : clazz.getMethods()) { webMethod = getPrivMethodAnnotation(method, WebMethod.class); if (webMethod != null && !webMethod.exclude()) { usesWebMethod = true; break; } } }*/ for (Method method : clazz.getMethods()) { if (!clazz.isInterface()) { // if clazz is SEI, then all methods are web methods if (method.getDeclaringClass() == Object.class) continue; if (!getBooleanSystemProperty("com.sun.xml.internal.ws.legacyWebMethod")) { // legacy webMethod computation behaviour to be used if (!isWebMethodBySpec(method, clazz)) continue; } else { if (!isWebMethod(method)) continue; } } // TODO: binding can be null. We need to figure out how to post-process // RuntimeModel to link to WSDLModel processMethod(method); } //Add additional jaxb classes referenced by {@link XmlSeeAlso} XmlSeeAlso xmlSeeAlso = getAnnotation(clazz, XmlSeeAlso.class); if(xmlSeeAlso != null) model.addAdditionalClasses(xmlSeeAlso.value()); } /* * Section 3.3 of spec * Otherwise, the class implicitly defines a service endpoint interface (SEI) which * comprises all of the public methods that satisfy one of the following conditions: * 1. They are annotated with the javax.jws.WebMethod annotation with the exclude element set to * false or missing (since false is the default for this annotation element). * 2. They are not annotated with the javax.jws.WebMethod annotation but their declaring class has a * javax.jws.WebService annotation. * * also the method should non-static or non-final */ private boolean isWebMethodBySpec(Method method, Class clazz) { int modifiers = method.getModifiers(); boolean staticFinal = Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers); assert Modifier.isPublic(modifiers); assert !clazz.isInterface(); WebMethod webMethod = getAnnotation(method, WebMethod.class); if (webMethod != null) { if (webMethod.exclude()) { return false; // @WebMethod(exclude="true") } if (staticFinal) { throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATICFINAL(method)); } return true; // @WebMethod } if (staticFinal) { return false; } Class declClass = method.getDeclaringClass(); return getAnnotation(declClass, WebService.class) != null; } private boolean isWebMethod(Method method) { int modifiers = method.getModifiers(); if (Modifier.isStatic(modifiers) || Modifier.isFinal(modifiers)) return false; Class clazz = method.getDeclaringClass(); boolean declHasWebService = getAnnotation(clazz, WebService.class) != null; WebMethod webMethod = getAnnotation(method, WebMethod.class); if (webMethod != null && !webMethod.exclude() && declHasWebService) return true; return declHasWebService && !classUsesWebMethod.contains(clazz); } /** * creates a runtime model SOAPBinding from a javax.jws.soap.SOAPBinding object * @param soapBinding the javax.jws.soap.SOAPBinding to model * @return returns the runtime model SOAPBinding corresponding to soapBinding */ protected SOAPBindingImpl createBinding(SOAPBinding soapBinding) { SOAPBindingImpl rtSOAPBinding = new SOAPBindingImpl(); Style style = soapBinding!=null ? soapBinding.style() : Style.DOCUMENT; rtSOAPBinding.setStyle(style); assert bindingId != null; model.bindingId = bindingId; SOAPVersion soapVersion = bindingId.getSOAPVersion(); rtSOAPBinding.setSOAPVersion(soapVersion); return rtSOAPBinding; } /** * gets the namespace String for a given packageName * @param packageName the name of the package used to find a namespace. * can be empty. * @return the namespace for the specified packageName */ public static String getNamespace(@NotNull String packageName) { if (packageName.length() == 0) return null; StringTokenizer tokenizer = new StringTokenizer(packageName, "."); String[] tokens; if (tokenizer.countTokens() == 0) { tokens = new String[0]; } else { tokens = new String[tokenizer.countTokens()]; for (int i=tokenizer.countTokens()-1; i >= 0; i--) { tokens[i] = tokenizer.nextToken(); } } StringBuilder namespace = new StringBuilder("http://"); for (int i=0; i exception) { return EXCEPTION_CLASS.isAssignableFrom(exception) && !(RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || isRemoteException(exception)); } /** * creates the runtime model for a method on the portClass * @param method the method to model */ private void processMethod(Method method) { // int mods = method.getModifiers(); WebMethod webMethod = getAnnotation(method, WebMethod.class); if (webMethod != null && webMethod.exclude()) return; /* validations are already done if (!Modifier.isPublic(mods) || Modifier.isStatic(mods)) { if(webMethod != null) { // if the user put @WebMethod on these non-qualifying method, // it's an error if(Modifier.isStatic(mods)) throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_NONSTATIC(method)); else throw new RuntimeModelerException(ModelerMessages.localizableRUNTIME_MODELER_WEBMETHOD_MUST_BE_PUBLIC(method)); } return; } if (webMethod != null && webMethod.exclude()) return; */ String methodName = method.getName(); boolean isOneway = (getAnnotation(method, Oneway.class) != null); //Check that oneway methods don't thorw any checked exceptions if (isOneway) { for (Class exception : method.getExceptionTypes()) { if(isServiceException(exception)) { throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.checked.exceptions", portClass.getCanonicalName(), methodName, exception.getName()); } } } JavaMethodImpl javaMethod; //Class implementorClass = portClass; if (method.getDeclaringClass()==portClass) { javaMethod = new JavaMethodImpl(model,method,method,metadataReader); } else { try { Method tmpMethod = portClass.getMethod(method.getName(), method.getParameterTypes()); javaMethod = new JavaMethodImpl(model,tmpMethod,method,metadataReader); } catch (NoSuchMethodException e) { throw new RuntimeModelerException("runtime.modeler.method.not.found", method.getName(), portClass.getName()); } } //set MEP -oneway, async, req/resp MEP mep = getMEP(method); javaMethod.setMEP(mep); String action = null; String operationName = method.getName(); if (webMethod != null ) { action = webMethod.action(); operationName = webMethod.operationName().length() > 0 ? webMethod.operationName() : operationName; } //override the @WebMethod.action value by the one from the WSDL if(binding != null){ WSDLBoundOperation bo = binding.getBinding().get(new QName(targetNamespace, operationName)); if(bo != null){ WSDLInput wsdlInput = bo.getOperation().getInput(); String wsaAction = wsdlInput.getAction(); if(wsaAction != null && !wsdlInput.isDefaultAction()) action = wsaAction; else action = bo.getSOAPAction(); } } javaMethod.setOperationQName(new QName(targetNamespace,operationName)); SOAPBinding methodBinding = getAnnotation(method, SOAPBinding.class); if(methodBinding != null && methodBinding.style() == SOAPBinding.Style.RPC) { logger.warning(ModelerMessages.RUNTIMEMODELER_INVALID_SOAPBINDING_ON_METHOD(methodBinding, method.getName(), method.getDeclaringClass().getName())); } else if (methodBinding == null && !method.getDeclaringClass().equals(portClass)) { methodBinding = getAnnotation(method.getDeclaringClass(), SOAPBinding.class); if (methodBinding != null && methodBinding.style() == SOAPBinding.Style.RPC && methodBinding.parameterStyle() == SOAPBinding.ParameterStyle.BARE) { throw new RuntimeModelerException("runtime.modeler.invalid.soapbinding.parameterstyle", methodBinding, method.getDeclaringClass()); } } if(methodBinding!= null && defaultBinding.getStyle() != methodBinding.style()) { throw new RuntimeModelerException("runtime.modeler.soapbinding.conflict", methodBinding.style(), method.getName(),defaultBinding.getStyle()); } boolean methodIsWrapped = isWrapped; Style style = defaultBinding.getStyle(); if (methodBinding != null) { SOAPBindingImpl mySOAPBinding = createBinding(methodBinding); style = mySOAPBinding.getStyle(); if (action != null) mySOAPBinding.setSOAPAction(action); methodIsWrapped = methodBinding.parameterStyle().equals( WRAPPED); javaMethod.setBinding(mySOAPBinding); } else { SOAPBindingImpl sb = new SOAPBindingImpl(defaultBinding); if (action != null) { sb.setSOAPAction(action); } else { String defaults = SOAPVersion.SOAP_11 == sb.getSOAPVersion() ? "" : null; sb.setSOAPAction(defaults); } javaMethod.setBinding(sb); } if (!methodIsWrapped) { processDocBareMethod(javaMethod, operationName, method); } else if (style.equals(Style.DOCUMENT)) { processDocWrappedMethod(javaMethod, methodName, operationName, method); } else { processRpcMethod(javaMethod, methodName, operationName, method); } model.addJavaMethod(javaMethod); } private MEP getMEP(Method m){ if (getAnnotation(m, Oneway.class)!= null) { return MEP.ONE_WAY; } if(Response.class.isAssignableFrom(m.getReturnType())){ return MEP.ASYNC_POLL; }else if(Future.class.isAssignableFrom(m.getReturnType())){ return MEP.ASYNC_CALLBACK; } return MEP.REQUEST_RESPONSE; } /** * models a document/literal wrapped method * @param javaMethod the runtime model JavaMethod instance being created * @param methodName the runtime model JavaMethod instance being created * @param operationName the runtime model JavaMethod instance being created * @param method the method to model */ protected void processDocWrappedMethod(JavaMethodImpl javaMethod, String methodName, String operationName, Method method) { boolean methodHasHeaderParams = false; boolean isOneway = getAnnotation(method, Oneway.class)!= null; RequestWrapper reqWrapper = getAnnotation(method,RequestWrapper.class); ResponseWrapper resWrapper = getAnnotation(method,ResponseWrapper.class); String beanPackage = packageName + PD_JAXWS_PACKAGE_PD; if (packageName == null || packageName.length() == 0) { beanPackage = JAXWS_PACKAGE_PD; } String requestClassName; if(reqWrapper != null && reqWrapper.className().length()>0){ requestClassName = reqWrapper.className(); }else{ requestClassName = beanPackage + capitalize(method.getName()); } String responseClassName; if(resWrapper != null && resWrapper.className().length()>0){ responseClassName = resWrapper.className(); }else{ responseClassName = beanPackage + capitalize(method.getName()) + RESPONSE; } String reqName = operationName; String reqNamespace = targetNamespace; String reqPartName = "parameters"; if (reqWrapper != null) { if (reqWrapper.targetNamespace().length() > 0) reqNamespace = reqWrapper.targetNamespace(); if (reqWrapper.localName().length() > 0) reqName = reqWrapper.localName(); try { if (reqWrapper.partName().length() > 0) reqPartName = reqWrapper.partName(); } catch(LinkageError e) { //2.1 API dopes n't have this method //Do nothing, just default to "parameters" } } QName reqElementName = new QName(reqNamespace, reqName); javaMethod.setRequestPayloadName(reqElementName); Class requestClass = getRequestWrapperClass(requestClassName, method, reqElementName); Class responseClass = null; String resName = operationName+"Response"; String resNamespace = targetNamespace; QName resElementName = null; String resPartName = "parameters"; if (!isOneway) { if (resWrapper != null) { if (resWrapper.targetNamespace().length() > 0) resNamespace = resWrapper.targetNamespace(); if (resWrapper.localName().length() > 0) resName = resWrapper.localName(); try { if (resWrapper.partName().length() > 0) resPartName = resWrapper.partName(); } catch (LinkageError e) { //2.1 API does n't have this method //Do nothing, just default to "parameters" } } resElementName = new QName(resNamespace, resName); responseClass = getResponseWrapperClass(responseClassName, method, resElementName); } TypeInfo typeRef = new TypeInfo(reqElementName, requestClass); typeRef.setNillable(false); WrapperParameter requestWrapper = new WrapperParameter(javaMethod, typeRef, Mode.IN, 0); requestWrapper.setPartName(reqPartName); requestWrapper.setBinding(ParameterBinding.BODY); javaMethod.addParameter(requestWrapper); WrapperParameter responseWrapper = null; if (!isOneway) { typeRef = new TypeInfo(resElementName, responseClass); typeRef.setNillable(false); responseWrapper = new WrapperParameter(javaMethod, typeRef, Mode.OUT, -1); javaMethod.addParameter(responseWrapper); responseWrapper.setBinding(ParameterBinding.BODY); } // return value WebResult webResult = getAnnotation(method, WebResult.class); XmlElement xmlElem = getAnnotation(method, XmlElement.class); QName resultQName = getReturnQName(method, webResult, xmlElem); Class returnType = method.getReturnType(); boolean isResultHeader = false; if (webResult != null) { isResultHeader = webResult.header(); methodHasHeaderParams = isResultHeader || methodHasHeaderParams; if (isResultHeader && xmlElem != null) { throw new RuntimeModelerException("@XmlElement cannot be specified on method "+method+" as the return value is bound to header"); } if (resultQName.getNamespaceURI().length() == 0 && webResult.header()) { // headers must have a namespace resultQName = new QName(targetNamespace, resultQName.getLocalPart()); } } if(javaMethod.isAsync()){ returnType = getAsyncReturnType(method, returnType); resultQName = new QName(RETURN); } resultQName = qualifyWrappeeIfNeeded(resultQName, resNamespace); if (!isOneway && (returnType != null) && (!returnType.getName().equals("void"))) { Annotation[] rann = getAnnotations(method); if (resultQName.getLocalPart() != null) { TypeInfo rTypeReference = new TypeInfo(resultQName, returnType, rann); metadataReader.getProperties(rTypeReference.properties(), method); rTypeReference.setGenericType(method.getGenericReturnType()); ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1); if (isResultHeader) { returnParameter.setBinding(ParameterBinding.HEADER); javaMethod.addParameter(returnParameter); } else { returnParameter.setBinding(ParameterBinding.BODY); responseWrapper.addWrapperChild(returnParameter); } } } //get WebParam Class[] parameterTypes = method.getParameterTypes(); Type[] genericParameterTypes = method.getGenericParameterTypes(); Annotation[][] pannotations = getParamAnnotations(method); int pos = 0; for (Class clazzType : parameterTypes) { String partName=null; String paramName = "arg"+pos; //String paramNamespace = ""; boolean isHeader = false; if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){ continue; } boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType); //set the actual type argument of Holder in the TypeReference if (isHolder) { if(clazzType==Holder.class){ clazzType = erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]); } } Mode paramMode = isHolder ? Mode.INOUT : Mode.IN; WebParam webParam = null; xmlElem = null; for (Annotation annotation : pannotations[pos]) { if (annotation.annotationType() == WebParam.class) webParam = (WebParam)annotation; else if (annotation.annotationType() == XmlElement.class) xmlElem = (XmlElement)annotation; } QName paramQName = getParameterQName(method, webParam, xmlElem, paramName); if (webParam != null) { isHeader = webParam.header(); methodHasHeaderParams = isHeader || methodHasHeaderParams; if (isHeader && xmlElem != null) { throw new RuntimeModelerException("@XmlElement cannot be specified on method "+method+" parameter that is bound to header"); } if(webParam.partName().length() > 0) partName = webParam.partName(); else partName = paramQName.getLocalPart(); if (isHeader && paramQName.getNamespaceURI().equals("")) { // headers cannot be in empty namespace paramQName = new QName(targetNamespace, paramQName.getLocalPart()); } paramMode = webParam.mode(); if (isHolder && paramMode == Mode.IN) paramMode = Mode.INOUT; } paramQName = qualifyWrappeeIfNeeded(paramQName, reqNamespace); typeRef = new TypeInfo(paramQName, clazzType, pannotations[pos]); metadataReader.getProperties(typeRef.properties(), method, pos); typeRef.setGenericType(genericParameterTypes[pos]); ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++); if (isHeader) { param.setBinding(ParameterBinding.HEADER); javaMethod.addParameter(param); param.setPartName(partName); } else { param.setBinding(ParameterBinding.BODY); if (paramMode!=Mode.OUT) { requestWrapper.addWrapperChild(param); } if (paramMode!=Mode.IN) { if (isOneway) { throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.out.parameters", portClass.getCanonicalName(), methodName); } responseWrapper.addWrapperChild(param); } } } //If the method has any parameter or return type that is bound to a header, use "result" as part name to avoid // name collison of same input part name and output part name ("parameters") shown up as param names on the // client mapping. if(methodHasHeaderParams) { resPartName = "result"; } if(responseWrapper != null) responseWrapper.setPartName(resPartName); processExceptions(javaMethod, method); } private QName qualifyWrappeeIfNeeded(QName resultQName, String ns) { Object o = config.properties().get(DocWrappeeNamespapceQualified); boolean qualified = (o!= null && o instanceof Boolean) ? ((Boolean) o) : false; if (qualified) { if (resultQName.getNamespaceURI() == null || "".equals(resultQName.getNamespaceURI())) { return new QName(ns, resultQName.getLocalPart()); } } return resultQName; } /** * models a rpc/literal method * @param javaMethod the runtime model JavaMethod instance being created * @param methodName the name of the method being modeled. * @param operationName the WSDL operation name for this method * @param method the runtime model JavaMethod instance being created */ protected void processRpcMethod(JavaMethodImpl javaMethod, String methodName, String operationName, Method method) { boolean isOneway = getAnnotation(method, Oneway.class) != null; // use Map to build parameters in the part order when they are known. // if part is unbound, we just put them at the end, and for that we // use a large index (10000+) to avoid colliding with ordered ones. // this assumes that there's no operation with # of parameters > 10000, // but I think it's a pretty safe assumption - KK. Map resRpcParams = new TreeMap(); Map reqRpcParams = new TreeMap(); //Lets take the service namespace and overwrite it with the one we get it from wsdl String reqNamespace = targetNamespace; String respNamespace = targetNamespace; if(binding != null && Style.RPC.equals(binding.getBinding().getStyle())){ QName opQName = new QName(binding.getBinding().getPortTypeName().getNamespaceURI(), operationName); WSDLBoundOperation op = binding.getBinding().get(opQName); if(op != null){ //it cant be null, but lets not fail and try to work with service namespce if(op.getRequestNamespace() != null){ reqNamespace = op.getRequestNamespace(); } //it cant be null, but lets not fail and try to work with service namespce if(op.getResponseNamespace() != null){ respNamespace = op.getResponseNamespace(); } } } QName reqElementName = new QName(reqNamespace, operationName); javaMethod.setRequestPayloadName(reqElementName); QName resElementName = null; if (!isOneway) { resElementName = new QName(respNamespace, operationName+RESPONSE); } Class wrapperType = WrapperComposite.class; TypeInfo typeRef = new TypeInfo(reqElementName, wrapperType); WrapperParameter requestWrapper = new WrapperParameter(javaMethod, typeRef, Mode.IN, 0); requestWrapper.setInBinding(ParameterBinding.BODY); javaMethod.addParameter(requestWrapper); WrapperParameter responseWrapper = null; if (!isOneway) { typeRef = new TypeInfo(resElementName, wrapperType); responseWrapper = new WrapperParameter(javaMethod, typeRef, Mode.OUT, -1); responseWrapper.setOutBinding(ParameterBinding.BODY); javaMethod.addParameter(responseWrapper); } Class returnType = method.getReturnType(); String resultName = RETURN; String resultTNS = targetNamespace; String resultPartName = resultName; boolean isResultHeader = false; WebResult webResult = getAnnotation(method, WebResult.class); if (webResult != null) { isResultHeader = webResult.header(); if (webResult.name().length() > 0) resultName = webResult.name(); if (webResult.partName().length() > 0) { resultPartName = webResult.partName(); if (!isResultHeader) resultName = resultPartName; } else resultPartName = resultName; if (webResult.targetNamespace().length() > 0) resultTNS = webResult.targetNamespace(); isResultHeader = webResult.header(); } QName resultQName; if (isResultHeader) resultQName = new QName(resultTNS, resultName); else resultQName = new QName(resultName); if(javaMethod.isAsync()){ returnType = getAsyncReturnType(method, returnType); } if (!isOneway && returnType!=null && returnType!=void.class) { Annotation[] rann = getAnnotations(method); TypeInfo rTypeReference = new TypeInfo(resultQName, returnType, rann); metadataReader.getProperties(rTypeReference.properties(), method); rTypeReference.setGenericType(method.getGenericReturnType()); ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1); returnParameter.setPartName(resultPartName); if(isResultHeader){ returnParameter.setBinding(ParameterBinding.HEADER); javaMethod.addParameter(returnParameter); rTypeReference.setGlobalElement(true); }else{ ParameterBinding rb = getBinding(operationName, resultPartName, false, Mode.OUT); returnParameter.setBinding(rb); if(rb.isBody()){ rTypeReference.setGlobalElement(false); WSDLPart p = getPart(new QName(targetNamespace,operationName), resultPartName, Mode.OUT); if(p == null) resRpcParams.put(resRpcParams.size()+10000, returnParameter); else resRpcParams.put(p.getIndex(), returnParameter); }else{ javaMethod.addParameter(returnParameter); } } } //get WebParam Class[] parameterTypes = method.getParameterTypes(); Type[] genericParameterTypes = method.getGenericParameterTypes(); Annotation[][] pannotations = getParamAnnotations(method); int pos = 0; for (Class clazzType : parameterTypes) { String paramName = ""; String paramNamespace = ""; String partName = ""; boolean isHeader = false; if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){ continue; } boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType); //set the actual type argument of Holder in the TypeReference if (isHolder) { if (clazzType==Holder.class) clazzType = erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]); } Mode paramMode = isHolder ? Mode.INOUT : Mode.IN; for (Annotation annotation : pannotations[pos]) { if (annotation.annotationType() == javax.jws.WebParam.class) { javax.jws.WebParam webParam = (javax.jws.WebParam) annotation; paramName = webParam.name(); partName = webParam.partName(); isHeader = webParam.header(); WebParam.Mode mode = webParam.mode(); paramNamespace = webParam.targetNamespace(); if (isHolder && mode == Mode.IN) mode = Mode.INOUT; paramMode = mode; break; } } if (paramName.length() == 0) { paramName = "arg"+pos; } if (partName.length() == 0) { partName = paramName; } else if (!isHeader) { paramName = partName; } if (partName.length() == 0) { partName = paramName; } QName paramQName; if (!isHeader) { //its rpclit body param, set namespace to "" paramQName = new QName("", paramName); } else { if (paramNamespace.length() == 0) paramNamespace = targetNamespace; paramQName = new QName(paramNamespace, paramName); } typeRef = new TypeInfo(paramQName, clazzType, pannotations[pos]); metadataReader.getProperties(typeRef.properties(), method, pos); typeRef.setGenericType(genericParameterTypes[pos]); ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++); param.setPartName(partName); if(paramMode == Mode.INOUT){ ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN); param.setInBinding(pb); pb = getBinding(operationName, partName, isHeader, Mode.OUT); param.setOutBinding(pb); }else{ if (isHeader) { typeRef.setGlobalElement(true); param.setBinding(ParameterBinding.HEADER); } else { ParameterBinding pb = getBinding(operationName, partName, false, paramMode); param.setBinding(pb); } } if(param.getInBinding().isBody()){ typeRef.setGlobalElement(false); if(!param.isOUT()){ WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.IN); if(p == null) reqRpcParams.put(reqRpcParams.size()+10000, param); else reqRpcParams.put(param.getIndex(), param); } if(!param.isIN()){ if (isOneway) { throw new RuntimeModelerException("runtime.modeler.oneway.operation.no.out.parameters", portClass.getCanonicalName(), methodName); } WSDLPart p = getPart(new QName(targetNamespace,operationName), partName, Mode.OUT); if(p == null) resRpcParams.put(resRpcParams.size()+10000, param); else resRpcParams.put(p.getIndex(), param); } }else{ javaMethod.addParameter(param); } } for (ParameterImpl p : reqRpcParams.values()) requestWrapper.addWrapperChild(p); for (ParameterImpl p : resRpcParams.values()) responseWrapper.addWrapperChild(p); processExceptions(javaMethod, method); } /** * models the exceptions thrown by method and adds them to the javaMethod * runtime model object * @param javaMethod the runtime model object to add the exception model objects to * @param method the method from which to find the exceptions to model */ protected void processExceptions(JavaMethodImpl javaMethod, Method method) { Action actionAnn = getAnnotation(method, Action.class); FaultAction[] faultActions = {}; if(actionAnn != null) faultActions = actionAnn.fault(); for (Class exception : method.getExceptionTypes()) { //Exclude RuntimeException, RemoteException and Error etc if (!EXCEPTION_CLASS.isAssignableFrom(exception)) continue; if (RUNTIME_EXCEPTION_CLASS.isAssignableFrom(exception) || isRemoteException(exception)) continue; if (getAnnotation(exception, javax.xml.bind.annotation.XmlTransient.class) != null) continue; Class exceptionBean; Annotation[] anns; WebFault webFault = getAnnotation(exception, WebFault.class); Method faultInfoMethod = getWSDLExceptionFaultInfo(exception); ExceptionType exceptionType = ExceptionType.WSDLException; String namespace = targetNamespace; String name = exception.getSimpleName(); String beanPackage = packageName + PD_JAXWS_PACKAGE_PD; if (packageName.length() == 0) beanPackage = JAXWS_PACKAGE_PD; String className = beanPackage+ name + BEAN; String messageName = exception.getSimpleName(); if (webFault != null) { if (webFault.faultBean().length()>0) className = webFault.faultBean(); if (webFault.name().length()>0) name = webFault.name(); if (webFault.targetNamespace().length()>0) namespace = webFault.targetNamespace(); if (webFault.messageName().length()>0) messageName = webFault.messageName(); } if (faultInfoMethod == null) { exceptionBean = getExceptionBeanClass(className, exception, name, namespace); exceptionType = ExceptionType.UserDefined; anns = getAnnotations(exceptionBean); } else { exceptionBean = faultInfoMethod.getReturnType(); anns = getAnnotations(faultInfoMethod); } QName faultName = new QName(namespace, name); TypeInfo typeRef = new TypeInfo(faultName, exceptionBean, anns); CheckedExceptionImpl checkedException = new CheckedExceptionImpl(javaMethod, exception, typeRef, exceptionType); checkedException.setMessageName(messageName); checkedException.setFaultInfoGetter(faultInfoMethod); for(FaultAction fa: faultActions) { if(fa.className().equals(exception) && !fa.value().equals("")) { checkedException.setFaultAction(fa.value()); break; } } javaMethod.addException(checkedException); } } /** * returns the method that corresponds to "getFaultInfo". Returns null if this is not an * exception generated from a WSDL * @param exception the class to search for the "getFaultInfo" method * @return the method named "getFaultInfo" if this is an exception generated from WSDL or an * exception that contains the WebFault annotation. Otherwise it returns null */ protected Method getWSDLExceptionFaultInfo(Class exception) { // if (!exception.isAnnotationPresent(WebFault.class)) if (getAnnotation(exception, WebFault.class) == null) return null; try { return exception.getMethod("getFaultInfo"); } catch (NoSuchMethodException e) { return null; } } /** * models a document/literal bare method * @param javaMethod the runtime model JavaMethod instance being created * @param operationName the runtime model JavaMethod instance being created * @param method the runtime model JavaMethod instance being created */ protected void processDocBareMethod(JavaMethodImpl javaMethod, String operationName, Method method) { String resultName = operationName+RESPONSE; String resultTNS = targetNamespace; String resultPartName = null; boolean isResultHeader = false; WebResult webResult = getAnnotation(method, WebResult.class); if (webResult != null) { if (webResult.name().length() > 0) resultName = webResult.name(); if (webResult.targetNamespace().length() > 0) resultTNS = webResult.targetNamespace(); resultPartName = webResult.partName(); isResultHeader = webResult.header(); } Class returnType = method.getReturnType(); Type gReturnType = method.getGenericReturnType(); if(javaMethod.isAsync()){ returnType = getAsyncReturnType(method, returnType); } if ((returnType != null) && (!returnType.getName().equals("void"))) { Annotation[] rann = getAnnotations(method); if (resultName != null) { QName responseQName = new QName(resultTNS, resultName); TypeInfo rTypeReference = new TypeInfo(responseQName, returnType, rann); rTypeReference.setGenericType(gReturnType); metadataReader.getProperties(rTypeReference.properties(), method); ParameterImpl returnParameter = new ParameterImpl(javaMethod, rTypeReference, Mode.OUT, -1); if(resultPartName == null || (resultPartName.length() == 0)){ resultPartName = resultName; } returnParameter.setPartName(resultPartName); if(isResultHeader){ returnParameter.setBinding(ParameterBinding.HEADER); }else{ ParameterBinding rb = getBinding(operationName, resultPartName, false, Mode.OUT); returnParameter.setBinding(rb); } javaMethod.addParameter(returnParameter); } } //get WebParam Class[] parameterTypes = method.getParameterTypes(); Type[] genericParameterTypes = method.getGenericParameterTypes(); Annotation[][] pannotations = getParamAnnotations(method); int pos = 0; for (Class clazzType : parameterTypes) { String paramName = operationName; //method.getName(); String partName = null; String requestNamespace = targetNamespace; boolean isHeader = false; //async if(javaMethod.isAsync() && AsyncHandler.class.isAssignableFrom(clazzType)){ continue; } boolean isHolder = HOLDER_CLASS.isAssignableFrom(clazzType); //set the actual type argument of Holder in the TypeReference if (isHolder) { if (clazzType==Holder.class) clazzType = erasure(((ParameterizedType)genericParameterTypes[pos]).getActualTypeArguments()[0]); } Mode paramMode = isHolder ? Mode.INOUT : Mode.IN; for (Annotation annotation : pannotations[pos]) { if (annotation.annotationType() == javax.jws.WebParam.class) { javax.jws.WebParam webParam = (javax.jws.WebParam) annotation; paramMode = webParam.mode(); if (isHolder && paramMode == Mode.IN) paramMode = Mode.INOUT; isHeader = webParam.header(); if(isHeader) paramName = "arg"+pos; if(paramMode == Mode.OUT && !isHeader) paramName = operationName+RESPONSE; if (webParam.name().length() > 0) paramName = webParam.name(); partName = webParam.partName(); if (!webParam.targetNamespace().equals("")) { requestNamespace = webParam.targetNamespace(); } break; } } QName requestQName = new QName(requestNamespace, paramName); if (!isHeader && paramMode != Mode.OUT) javaMethod.setRequestPayloadName(requestQName); //doclit/wrapped TypeInfo typeRef = //operationName with upper 1 char new TypeInfo(requestQName, clazzType, pannotations[pos]); metadataReader.getProperties(typeRef.properties(), method, pos); typeRef.setGenericType(genericParameterTypes[pos]); ParameterImpl param = new ParameterImpl(javaMethod, typeRef, paramMode, pos++); if(partName == null || (partName.length() == 0)){ partName = paramName; } param.setPartName(partName); if(paramMode == Mode.INOUT){ ParameterBinding pb = getBinding(operationName, partName, isHeader, Mode.IN); param.setInBinding(pb); pb = getBinding(operationName, partName, isHeader, Mode.OUT); param.setOutBinding(pb); }else{ if (isHeader){ param.setBinding(ParameterBinding.HEADER); }else{ ParameterBinding pb = getBinding(operationName, partName, false, paramMode); param.setBinding(pb); } } javaMethod.addParameter(param); } validateDocBare(javaMethod); processExceptions(javaMethod, method); } // Does a conservative check if there is only one BODY part for input // and output message. We are not considering INOUT parameters at this // time since binding information is not applied. Also, there isn't // anyway to represent some cases in SEI. For example, a INOUT parameter // could be bound to body for input message, header for OUTPUT message // in wsdl:binding private void validateDocBare(JavaMethodImpl javaMethod) { int numInBodyBindings = 0; for(Parameter param : javaMethod.getRequestParameters()){ if(param.getBinding().equals(ParameterBinding.BODY) && param.isIN()){ numInBodyBindings++; } if(numInBodyBindings > 1){ throw new RuntimeModelerException(ModelerMessages.localizableNOT_A_VALID_BARE_METHOD(portClass.getName(), javaMethod.getMethod().getName())); } } int numOutBodyBindings = 0; for(Parameter param : javaMethod.getResponseParameters()){ if(param.getBinding().equals(ParameterBinding.BODY) && param.isOUT()){ numOutBodyBindings++; } if(numOutBodyBindings > 1){ throw new RuntimeModelerException(ModelerMessages.localizableNOT_A_VALID_BARE_METHOD(portClass.getName(), javaMethod.getMethod().getName())); } } } private Class getAsyncReturnType(Method method, Class returnType) { if(Response.class.isAssignableFrom(returnType)){ Type ret = method.getGenericReturnType(); return erasure(((ParameterizedType)ret).getActualTypeArguments()[0]); }else{ Type[] types = method.getGenericParameterTypes(); Class[] params = method.getParameterTypes(); int i = 0; for(Class cls : params){ if(AsyncHandler.class.isAssignableFrom(cls)){ return erasure(((ParameterizedType)types[i]).getActualTypeArguments()[0]); } i++; } } return returnType; } /** * utility to capitalize the first letter in a string * @param name the string to capitalize * @return the capitalized string */ public static String capitalize(String name) { if (name == null || name.length() == 0) { return name; } char chars[] = name.toCharArray(); chars[0] = Character.toUpperCase(chars[0]); return new String(chars); } /* * Return service QName */ /** * gets the wsdl:serviceName for a given implementation class * @param implClass the implementation class * @return the wsdl:serviceName for the implClass */ public static QName getServiceName(Class implClass) { return getServiceName(implClass, null); } public static QName getServiceName(Class implClass, boolean isStandard) { return getServiceName(implClass, null, isStandard); } public static QName getServiceName(Class implClass, MetadataReader reader) { return getServiceName(implClass, reader, true); } public static QName getServiceName(Class implClass, MetadataReader reader, boolean isStandard) { if (implClass.isInterface()) { throw new RuntimeModelerException("runtime.modeler.cannot.get.serviceName.from.interface", implClass.getCanonicalName()); } String name = implClass.getSimpleName()+SERVICE; String packageName = ""; if (implClass.getPackage() != null) packageName = implClass.getPackage().getName(); WebService webService = getAnnotation(WebService.class, implClass, reader); if (isStandard && webService == null) { throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation", implClass.getCanonicalName()); } if (webService != null && webService.serviceName().length() > 0) { name = webService.serviceName(); } String targetNamespace = getNamespace(packageName); if (webService != null && webService.targetNamespace().length() > 0) { targetNamespace = webService.targetNamespace(); } else if (targetNamespace == null) { throw new RuntimeModelerException("runtime.modeler.no.package", implClass.getName()); } return new QName(targetNamespace, name); } /** * gets the wsdl:portName for a given implementation class * @param implClass the implementation class * @param targetNamespace Namespace URI for service name * @return the wsdl:portName for the implClass */ public static QName getPortName(Class implClass, String targetNamespace) { return getPortName(implClass, null, targetNamespace); } public static QName getPortName(Class implClass, String targetNamespace, boolean isStandard) { return getPortName(implClass, null, targetNamespace, isStandard); } public static QName getPortName(Class implClass, MetadataReader reader, String targetNamespace) { return getPortName(implClass, reader, targetNamespace, true); } public static QName getPortName(Class implClass, MetadataReader reader, String targetNamespace, boolean isStandard) { WebService webService = getAnnotation(WebService.class, implClass, reader); if (isStandard && webService == null) { throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation", implClass.getCanonicalName()); } String name; if (webService != null && webService.portName().length() > 0) { name = webService.portName(); } else if (webService != null && webService.name().length() > 0) { name = webService.name()+PORT; } else { name = implClass.getSimpleName()+PORT; } if (targetNamespace == null) { if (webService != null && webService.targetNamespace().length() > 0) { targetNamespace = webService.targetNamespace(); } else { String packageName = null; if (implClass.getPackage() != null) { packageName = implClass.getPackage().getName(); } if (packageName != null) { targetNamespace = getNamespace(packageName); } if (targetNamespace == null) { throw new RuntimeModelerException("runtime.modeler.no.package", implClass.getName()); } } } return new QName(targetNamespace, name); } static A getAnnotation(Class t, Class cls, MetadataReader reader) { return (reader == null)? cls.getAnnotation(t) : reader.getAnnotation(t, cls); } /** * Gives portType QName from implementatorClass or SEI * @param implOrSeiClass cant be null * @return wsdl:portType@name, null if it could not find the annotated class. */ public static QName getPortTypeName(Class implOrSeiClass){ return getPortTypeName(implOrSeiClass, null, null); } public static QName getPortTypeName(Class implOrSeiClass, MetadataReader metadataReader){ return getPortTypeName(implOrSeiClass, null, metadataReader); } public static QName getPortTypeName(Class implOrSeiClass, String tns, MetadataReader reader){ assert(implOrSeiClass != null); WebService webService = getAnnotation(WebService.class, implOrSeiClass, reader); Class clazz = implOrSeiClass; if (webService == null) throw new RuntimeModelerException("runtime.modeler.no.webservice.annotation", implOrSeiClass.getCanonicalName()); if (!implOrSeiClass.isInterface()) { String epi = webService.endpointInterface(); if (epi.length() > 0) { try { clazz = Thread.currentThread().getContextClassLoader().loadClass(epi); } catch (ClassNotFoundException e) { throw new RuntimeModelerException("runtime.modeler.class.not.found", epi); } WebService ws = getAnnotation(WebService.class, clazz, reader); if (ws == null) { throw new RuntimeModelerException("runtime.modeler.endpoint.interface.no.webservice", webService.endpointInterface()); } } } webService = getAnnotation(WebService.class, clazz, reader); String name = webService.name(); if(name.length() == 0){ name = clazz.getSimpleName(); } if (tns == null || "".equals(tns.trim())) tns = webService.targetNamespace(); if (tns.length() == 0) tns = getNamespace(clazz.getPackage().getName()); if (tns == null) { throw new RuntimeModelerException("runtime.modeler.no.package", clazz.getName()); } return new QName(tns, name); } private ParameterBinding getBinding(String operation, String part, boolean isHeader, Mode mode){ if(binding == null){ if(isHeader) return ParameterBinding.HEADER; else return ParameterBinding.BODY; } QName opName = new QName(binding.getBinding().getPortType().getName().getNamespaceURI(), operation); return binding.getBinding().getBinding(opName, part, mode); } private WSDLPart getPart(QName opName, String partName, Mode mode){ if(binding != null){ WSDLBoundOperation bo = binding.getBinding().get(opName); if(bo != null) return bo.getPart(partName, mode); } return null; } /* * Returns true if an exception is a java.rmi.RemoteException or its subtype. * * @param exception * @return true if an exception is a java.rmi.RemoteException or its subtype, * false otherwise */ private boolean isRemoteException(Class exception) { Class c = exception; while (c != null && !REMOTE_EXCEPTION_CLASS.equals(c.getName())) { c = c.getSuperclass(); } return c != null; } private static Boolean getBooleanSystemProperty(final String prop) { return AccessController.doPrivileged( new java.security.PrivilegedAction() { public Boolean run() { String value = System.getProperty(prop); return value != null ? Boolean.valueOf(value) : Boolean.FALSE; } } ); } private static QName getReturnQName(Method method, WebResult webResult, XmlElement xmlElem) { String webResultName = null; if (webResult != null && webResult.name().length() > 0) { webResultName = webResult.name(); } String xmlElemName = null; if (xmlElem != null && !xmlElem.name().equals("##default")) { xmlElemName = xmlElem.name(); } if (xmlElemName != null && webResultName != null && !xmlElemName.equals(webResultName)) { throw new RuntimeModelerException("@XmlElement(name)="+xmlElemName+" and @WebResult(name)="+webResultName+" are different for method " +method); } String localPart = RETURN; if (webResultName != null) { localPart = webResultName; } else if (xmlElemName != null) { localPart = xmlElemName; } String webResultNS = null; if (webResult != null && webResult.targetNamespace().length() > 0) { webResultNS = webResult.targetNamespace(); } String xmlElemNS = null; if (xmlElem != null && !xmlElem.namespace().equals("##default")) { xmlElemNS = xmlElem.namespace(); } if (xmlElemNS != null && webResultNS != null && !xmlElemNS.equals(webResultNS)) { throw new RuntimeModelerException("@XmlElement(namespace)="+xmlElemNS+" and @WebResult(targetNamespace)="+webResultNS+" are different for method " +method); } String ns = ""; if (webResultNS != null) { ns = webResultNS; } else if (xmlElemNS != null) { ns = xmlElemNS; } return new QName(ns, localPart); } private static QName getParameterQName(Method method, WebParam webParam, XmlElement xmlElem, String paramDefault) { String webParamName = null; if (webParam != null && webParam.name().length() > 0) { webParamName = webParam.name(); } String xmlElemName = null; if (xmlElem != null && !xmlElem.name().equals("##default")) { xmlElemName = xmlElem.name(); } if (xmlElemName != null && webParamName != null && !xmlElemName.equals(webParamName)) { throw new RuntimeModelerException("@XmlElement(name)="+xmlElemName+" and @WebParam(name)="+webParamName+" are different for method " +method); } String localPart = paramDefault; if (webParamName != null) { localPart = webParamName; } else if (xmlElemName != null) { localPart = xmlElemName; } String webParamNS = null; if (webParam != null && webParam.targetNamespace().length() > 0) { webParamNS = webParam.targetNamespace(); } String xmlElemNS = null; if (xmlElem != null && !xmlElem.namespace().equals("##default")) { xmlElemNS = xmlElem.namespace(); } if (xmlElemNS != null && webParamNS != null && !xmlElemNS.equals(webParamNS)) { throw new RuntimeModelerException("@XmlElement(namespace)="+xmlElemNS+" and @WebParam(targetNamespace)="+webParamNS+" are different for method " +method); } String ns = ""; if (webParamNS != null) { ns = webParamNS; } else if (xmlElemNS != null) { ns = xmlElemNS; } return new QName(ns, localPart); } static public Class erasure(Type type) { return (Class)REFLECTION_NAVIGATOR.erasure(type); } }